setupapi: Implement SetupGetFileCompressionInfo on top of SetupGetFileCompressionInfoEx.
[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((DWORD*)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     GDI_ReleaseObj( hdc );
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         GDI_ReleaseObj( pfe->hdc );  /* 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) GDI_ReleaseObj( pfe->hdc );
715             pfe->hdc = 0;  /* make sure we don't try to release it later on */
716             ret = 0;
717         }
718     }
719     return ret;
720 }
721
722 /***********************************************************************
723  *              FONT_EnumInstance
724  *
725  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
726  *       We have to use other types because of the FONTENUMPROCW definition.
727  */
728 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
729                                        DWORD fType, LPARAM lp )
730 {
731     fontEnum32 *pfe = (fontEnum32*)lp;
732     INT ret = 1;
733     DC *dc;
734
735     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
736     if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
737         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
738        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
739     {
740         /* convert font metrics */
741         ENUMLOGFONTEXA logfont;
742         NEWTEXTMETRICEXA tmA;
743
744         pfe->dwFlags |= ENUM_CALLED;
745         if (!(pfe->dwFlags & ENUM_UNICODE))
746         {
747             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
748             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
749             plf = (LOGFONTW *)&logfont.elfLogFont;
750             ptm = (TEXTMETRICW *)&tmA;
751         }
752         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
753
754         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
755
756         /* get the lock again and make sure the DC is still valid */
757         dc = DC_GetDCPtr( pfe->hdc );
758         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
759         {
760             if (dc) GDI_ReleaseObj( pfe->hdc );
761             pfe->hdc = 0;  /* make sure we don't try to release it later on */
762             ret = 0;
763         }
764     }
765     return ret;
766 }
767
768 /***********************************************************************
769  *              EnumFontFamiliesEx      (GDI.613)
770  */
771 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
772                                    FONTENUMPROC16 efproc, LPARAM lParam,
773                                    DWORD dwFlags)
774 {
775     fontEnum16 fe16;
776     INT16       ret = 1, ret2;
777     DC*         dc = DC_GetDCPtr( HDC_32(hDC) );
778     NEWTEXTMETRICEX16 tm16;
779     ENUMLOGFONTEX16 lf16;
780     LOGFONTW lfW;
781     BOOL enum_gdi_fonts;
782
783     if (!dc) return 0;
784     FONT_LogFont16ToW(plf, &lfW);
785
786     fe16.hdc = HDC_32(hDC);
787     fe16.dc = dc;
788     fe16.physDev = dc->physDev;
789     fe16.lpLogFontParam = plf;
790     fe16.lpEnumFunc = efproc;
791     fe16.lpData = lParam;
792     fe16.lpTextMetric = &tm16;
793     fe16.lpLogFont = &lf16;
794     fe16.segTextMetric = MapLS( &tm16 );
795     fe16.segLogFont = MapLS( &lf16 );
796     fe16.dwFlags = 0;
797
798     enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
799
800     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
801     {
802         ret = 0;
803         goto done;
804     }
805
806     if (enum_gdi_fonts)
807         ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
808     fe16.dwFlags &= ~ENUM_CALLED;
809     if (ret && dc->funcs->pEnumDeviceFonts) {
810         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
811         if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
812             ret = ret2;
813     }
814 done:
815     UnMapLS( fe16.segTextMetric );
816     UnMapLS( fe16.segLogFont );
817     if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
818     return ret;
819 }
820
821 /***********************************************************************
822  *              FONT_EnumFontFamiliesEx
823  */
824 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
825                                     FONTENUMPROCW efproc,
826                                     LPARAM lParam, DWORD dwUnicode)
827 {
828     INT ret = 1, ret2;
829     DC *dc = DC_GetDCPtr( hDC );
830     fontEnum32 fe32;
831     BOOL enum_gdi_fonts;
832
833     if (!dc) return 0;
834
835     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
836           plf->lfCharSet);
837     fe32.lpLogFontParam = plf;
838     fe32.lpEnumFunc = efproc;
839     fe32.lpData = lParam;
840     fe32.dwFlags = dwUnicode;
841     fe32.hdc = hDC;
842     fe32.dc = dc;
843     fe32.physDev = dc->physDev;
844
845     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
846
847     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
848     {
849         ret = 0;
850         goto done;
851     }
852
853     if (enum_gdi_fonts)
854         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
855     fe32.dwFlags &= ~ENUM_CALLED;
856     if (ret && dc->funcs->pEnumDeviceFonts) {
857         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
858         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
859             ret = ret2;
860     }
861  done:
862     if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
863     return ret;
864 }
865
866 /***********************************************************************
867  *              EnumFontFamiliesExW     (GDI32.@)
868  */
869 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
870                                     FONTENUMPROCW efproc,
871                                     LPARAM lParam, DWORD dwFlags )
872 {
873     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
874 }
875
876 /***********************************************************************
877  *              EnumFontFamiliesExA     (GDI32.@)
878  */
879 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
880                                     FONTENUMPROCA efproc,
881                                     LPARAM lParam, DWORD dwFlags)
882 {
883     LOGFONTW lfW;
884     FONT_LogFontAToW( plf, &lfW );
885
886     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
887 }
888
889 /***********************************************************************
890  *              EnumFontFamilies        (GDI.330)
891  */
892 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
893                                  FONTENUMPROC16 efproc, LPARAM lpData )
894 {
895     LOGFONT16   lf;
896
897     lf.lfCharSet = DEFAULT_CHARSET;
898     if (lpFamily)
899     {
900         if (!*lpFamily) return 1;
901         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
902     }
903     else lf.lfFaceName[0] = '\0';
904
905     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
906 }
907
908 /***********************************************************************
909  *              EnumFontFamiliesA       (GDI32.@)
910  */
911 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
912                                   FONTENUMPROCA efproc, LPARAM lpData )
913 {
914     LOGFONTA    lf;
915
916     lf.lfCharSet = DEFAULT_CHARSET;
917     if (lpFamily)
918     {
919         if (!*lpFamily) return 1;
920         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
921     }
922     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
923
924     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
925 }
926
927 /***********************************************************************
928  *              EnumFontFamiliesW       (GDI32.@)
929  */
930 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
931                                   FONTENUMPROCW efproc, LPARAM lpData )
932 {
933     LOGFONTW  lf;
934
935     lf.lfCharSet = DEFAULT_CHARSET;
936     if (lpFamily)
937     {
938         if (!*lpFamily) return 1;
939         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
940     }
941     else lf.lfFaceName[0] = 0;
942
943     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
944 }
945
946 /***********************************************************************
947  *              EnumFonts               (GDI.70)
948  */
949 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
950                           LPARAM lpData )
951 {
952     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
953 }
954
955 /***********************************************************************
956  *              EnumFontsA              (GDI32.@)
957  */
958 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
959                            LPARAM lpData )
960 {
961     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
962 }
963
964 /***********************************************************************
965  *              EnumFontsW              (GDI32.@)
966  */
967 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
968                            LPARAM lpData )
969 {
970     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
971 }
972
973
974 /***********************************************************************
975  *           GetTextCharacterExtra    (GDI32.@)
976  */
977 INT WINAPI GetTextCharacterExtra( HDC hdc )
978 {
979     INT ret;
980     DC *dc = DC_GetDCPtr( hdc );
981     if (!dc) return 0x80000000;
982     ret = dc->charExtra;
983     GDI_ReleaseObj( hdc );
984     return ret;
985 }
986
987
988 /***********************************************************************
989  *           SetTextCharacterExtra    (GDI32.@)
990  */
991 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
992 {
993     INT prev;
994     DC * dc = DC_GetDCPtr( hdc );
995     if (!dc) return 0x80000000;
996     if (dc->funcs->pSetTextCharacterExtra)
997         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
998     else
999     {
1000         prev = dc->charExtra;
1001         dc->charExtra = extra;
1002     }
1003     GDI_ReleaseObj( hdc );
1004     return prev;
1005 }
1006
1007
1008 /***********************************************************************
1009  *           SetTextJustification    (GDI32.@)
1010  */
1011 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1012 {
1013     BOOL ret = TRUE;
1014     DC * dc = DC_GetDCPtr( hdc );
1015     if (!dc) return FALSE;
1016     if (dc->funcs->pSetTextJustification)
1017         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1018     else
1019     {
1020         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1021         if (!extra) breaks = 0;
1022         if (breaks)
1023         {
1024             dc->breakExtra = extra / breaks;
1025             dc->breakRem   = extra - (breaks * dc->breakExtra);
1026         }
1027         else
1028         {
1029             dc->breakExtra = 0;
1030             dc->breakRem   = 0;
1031         }
1032     }
1033     GDI_ReleaseObj( hdc );
1034     return ret;
1035 }
1036
1037
1038 /***********************************************************************
1039  *           GetTextFaceA    (GDI32.@)
1040  */
1041 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1042 {
1043     INT res = GetTextFaceW(hdc, 0, NULL);
1044     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1045     GetTextFaceW( hdc, res, nameW );
1046
1047     if (name)
1048     {
1049         if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1050             name[count-1] = 0;
1051         res = strlen(name);
1052     }
1053     else
1054         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1055     HeapFree( GetProcessHeap(), 0, nameW );
1056     return res;
1057 }
1058
1059 /***********************************************************************
1060  *           GetTextFaceW    (GDI32.@)
1061  */
1062 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1063 {
1064     FONTOBJ *font;
1065     INT     ret = 0;
1066
1067     DC * dc = DC_GetDCPtr( hdc );
1068     if (!dc) return 0;
1069
1070     if(dc->gdiFont)
1071         ret = WineEngGetTextFace(dc->gdiFont, count, name);
1072     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1073     {
1074         if (name)
1075         {
1076             lstrcpynW( name, font->logfont.lfFaceName, count );
1077             ret = strlenW(name);
1078         }
1079         else ret = strlenW(font->logfont.lfFaceName) + 1;
1080         GDI_ReleaseObj( dc->hFont );
1081     }
1082     GDI_ReleaseObj( hdc );
1083     return ret;
1084 }
1085
1086
1087 /***********************************************************************
1088  *           GetTextExtentPoint32A    (GDI32.@)
1089  *
1090  * See GetTextExtentPoint32W.
1091  */
1092 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1093                                      LPSIZE size )
1094 {
1095     BOOL ret = FALSE;
1096     INT wlen;
1097     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1098
1099     if (p) {
1100         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1101         HeapFree( GetProcessHeap(), 0, p );
1102     }
1103
1104     TRACE("(%p %s %d %p): returning %d x %d\n",
1105           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1106     return ret;
1107 }
1108
1109
1110 /***********************************************************************
1111  * GetTextExtentPoint32W [GDI32.@]
1112  *
1113  * Computes width/height for a string.
1114  *
1115  * Computes width and height of the specified string.
1116  *
1117  * RETURNS
1118  *    Success: TRUE
1119  *    Failure: FALSE
1120  */
1121 BOOL WINAPI GetTextExtentPoint32W(
1122     HDC hdc,     /* [in]  Handle of device context */
1123     LPCWSTR str,   /* [in]  Address of text string */
1124     INT count,   /* [in]  Number of characters in string */
1125     LPSIZE size) /* [out] Address of structure for string size */
1126 {
1127     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1128 }
1129
1130 /***********************************************************************
1131  * GetTextExtentPointI [GDI32.@]
1132  *
1133  * Computes width and height of the array of glyph indices.
1134  *
1135  * RETURNS
1136  *    Success: TRUE
1137  *    Failure: FALSE
1138  */
1139 BOOL WINAPI GetTextExtentPointI(
1140     HDC hdc,     /* [in]  Handle of device context */
1141     const WORD *indices,   /* [in]  Address of glyph index array */
1142     INT count,   /* [in]  Number of glyphs in array */
1143     LPSIZE size) /* [out] Address of structure for string size */
1144 {
1145     BOOL ret = FALSE;
1146     DC * dc = DC_GetDCPtr( hdc );
1147     if (!dc) return FALSE;
1148
1149     if(dc->gdiFont) {
1150         ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1151         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1152         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1153         size->cx += count * dc->charExtra;
1154     }
1155     else if(dc->funcs->pGetTextExtentExPoint) {
1156         FIXME("calling GetTextExtentExPoint\n");
1157         ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1158                                                 count, 0, NULL, NULL, size );
1159     }
1160
1161     GDI_ReleaseObj( hdc );
1162
1163     TRACE("(%p %p %d %p): returning %d x %d\n",
1164           hdc, indices, count, size, size->cx, size->cy );
1165     return ret;
1166 }
1167
1168
1169 /***********************************************************************
1170  *           GetTextExtentPointA    (GDI32.@)
1171  */
1172 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1173                                           LPSIZE size )
1174 {
1175     TRACE("not bug compatible.\n");
1176     return GetTextExtentPoint32A( hdc, str, count, size );
1177 }
1178
1179 /***********************************************************************
1180  *           GetTextExtentPointW   (GDI32.@)
1181  */
1182 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1183                                           LPSIZE size )
1184 {
1185     TRACE("not bug compatible.\n");
1186     return GetTextExtentPoint32W( hdc, str, count, size );
1187 }
1188
1189
1190 /***********************************************************************
1191  *           GetTextExtentExPointA    (GDI32.@)
1192  */
1193 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1194                                    INT maxExt, LPINT lpnFit,
1195                                    LPINT alpDx, LPSIZE size )
1196 {
1197     BOOL ret;
1198     INT wlen;
1199     INT *walpDx = NULL;
1200     LPWSTR p = NULL;
1201     
1202     if (alpDx &&
1203        NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1204        return FALSE;
1205     
1206     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1207     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1208     if (walpDx)
1209     {
1210         INT n = lpnFit ? *lpnFit : wlen;
1211         INT i, j;
1212         for(i = 0, j = 0; i < n; i++, j++)
1213         {
1214             alpDx[j] = walpDx[i];
1215             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1216         }
1217     }
1218     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1219     HeapFree( GetProcessHeap(), 0, p );
1220     HeapFree( GetProcessHeap(), 0, walpDx );
1221     return ret;
1222 }
1223
1224
1225 /***********************************************************************
1226  *           GetTextExtentExPointW    (GDI32.@)
1227  *
1228  * Return the size of the string as it would be if it was output properly by
1229  * e.g. TextOut.
1230  *
1231  * This should include
1232  * - Intercharacter spacing
1233  * - justification spacing (not yet done)
1234  * - kerning? see below
1235  *
1236  * Kerning.  Since kerning would be carried out by the rendering code it should
1237  * be done by the driver.  However they don't support it yet.  Also I am not
1238  * yet persuaded that (certainly under Win95) any kerning is actually done.
1239  *
1240  * str: According to MSDN this should be null-terminated.  That is not true; a
1241  *      null will not terminate it early.
1242  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1243  *       than count.  I have seen it be either the size of the full string or
1244  *       1 less than the size of the full string.  I have not seen it bear any
1245  *       resemblance to the portion that would fit.
1246  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1247  *         trailing intercharacter spacing and any trailing justification.
1248  *
1249  * FIXME
1250  * Currently we do this by measuring each character etc.  We should do it by
1251  * passing the request to the driver, perhaps by extending the
1252  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1253  * thinking about kerning issues and rounding issues in the justification.
1254  */
1255
1256 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1257                                    INT maxExt, LPINT lpnFit,
1258                                    LPINT alpDx, LPSIZE size )
1259 {
1260     INT nFit = 0;
1261     LPINT dxs = NULL;
1262     DC *dc;
1263     BOOL ret = FALSE;
1264     TEXTMETRICW tm;
1265
1266     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1267
1268     dc = DC_GetDCPtr(hdc);
1269     if (! dc)
1270         return FALSE;
1271
1272     GetTextMetricsW(hdc, &tm);
1273
1274     /* If we need to calculate nFit, then we need the partial extents even if
1275        the user hasn't provided us with an array.  */
1276     if (lpnFit)
1277     {
1278         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1279         if (! dxs)
1280         {
1281             GDI_ReleaseObj(hdc);
1282             SetLastError(ERROR_OUTOFMEMORY);
1283             return FALSE;
1284         }
1285     }
1286     else
1287         dxs = alpDx;
1288
1289     if (dc->gdiFont)
1290         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1291                                           0, NULL, dxs, size);
1292     else if (dc->funcs->pGetTextExtentExPoint)
1293         ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1294                                                0, NULL, dxs, size);
1295
1296     /* Perform device size to world size transformations.  */
1297     if (ret)
1298     {
1299         INT extra      = dc->charExtra,
1300         breakExtra = dc->breakExtra,
1301         breakRem   = dc->breakRem,
1302         i;
1303
1304         if (dxs)
1305         {
1306             for (i = 0; i < count; ++i)
1307             {
1308                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1309                 dxs[i] += (i+1) * extra;
1310                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1311                 {
1312                     dxs[i] += breakExtra;
1313                     if (breakRem > 0)
1314                     {
1315                         breakRem--;
1316                         dxs[i]++;
1317                     }
1318                 }
1319                 if (dxs[i] <= maxExt)
1320                     ++nFit;
1321             }
1322             breakRem = dc->breakRem;
1323         }
1324         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1325         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1326
1327         if (!dxs && count > 1 && (breakExtra || breakRem))
1328         {
1329             for (i = 0; i < count; i++)
1330             {
1331                 if (str[i] == tm.tmBreakChar)
1332                 {
1333                     size->cx += breakExtra;
1334                     if (breakRem > 0)
1335                     {
1336                         breakRem--;
1337                         (size->cx)++;
1338                     }
1339                 }
1340             }
1341         }
1342     }
1343
1344     if (lpnFit)
1345         *lpnFit = nFit;
1346
1347     if (! alpDx)
1348         HeapFree(GetProcessHeap(), 0, dxs);
1349
1350     GDI_ReleaseObj( hdc );
1351
1352     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1353     return ret;
1354 }
1355
1356 /***********************************************************************
1357  *           GetTextMetricsA    (GDI32.@)
1358  */
1359 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1360 {
1361     TEXTMETRICW tm32;
1362
1363     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1364     FONT_TextMetricWToA( &tm32, metrics );
1365     return TRUE;
1366 }
1367
1368 /***********************************************************************
1369  *           GetTextMetricsW    (GDI32.@)
1370  */
1371 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1372 {
1373     BOOL ret = FALSE;
1374     DC * dc = DC_GetDCPtr( hdc );
1375     if (!dc) return FALSE;
1376
1377     if (dc->gdiFont)
1378         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1379     else if (dc->funcs->pGetTextMetrics)
1380         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1381
1382     if (ret)
1383     {
1384     /* device layer returns values in device units
1385      * therefore we have to convert them to logical */
1386
1387         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1388         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1389
1390 #define WDPTOLP(x) ((x<0)?                                      \
1391                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1392                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1393 #define HDPTOLP(y) ((y<0)?                                      \
1394                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1395                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1396
1397     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1398     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1399     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1400     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1401     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1402     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1403     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1404     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1405         ret = TRUE;
1406 #undef WDPTOLP
1407 #undef HDPTOLP
1408     TRACE("text metrics:\n"
1409           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1410           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1411           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1412           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1413           "    PitchAndFamily = %02x\n"
1414           "    --------------------\n"
1415           "    InternalLeading = %i\n"
1416           "    Ascent = %i\n"
1417           "    Descent = %i\n"
1418           "    Height = %i\n",
1419           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1420           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1421           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1422           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1423           metrics->tmPitchAndFamily,
1424           metrics->tmInternalLeading,
1425           metrics->tmAscent,
1426           metrics->tmDescent,
1427           metrics->tmHeight );
1428     }
1429     GDI_ReleaseObj( hdc );
1430     return ret;
1431 }
1432
1433
1434 /***********************************************************************
1435  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1436  *
1437  * NOTES
1438  *    lpOTM should be LPOUTLINETEXTMETRIC
1439  *
1440  * RETURNS
1441  *    Success: Non-zero or size of required buffer
1442  *    Failure: 0
1443  */
1444 UINT16 WINAPI GetOutlineTextMetrics16(
1445     HDC16 hdc,    /* [in]  Handle of device context */
1446     UINT16 cbData, /* [in]  Size of metric data array */
1447     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1448 {
1449     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1450     return 0;
1451 }
1452
1453
1454 /***********************************************************************
1455  *              GetOutlineTextMetricsA (GDI32.@)
1456  * Gets metrics for TrueType fonts.
1457  *
1458  * NOTES
1459  *    If the supplied buffer isn't big enough Windows partially fills it up to
1460  *    its given length and returns that length.
1461  *
1462  * RETURNS
1463  *    Success: Non-zero or size of required buffer
1464  *    Failure: 0
1465  */
1466 UINT WINAPI GetOutlineTextMetricsA(
1467     HDC hdc,    /* [in]  Handle of device context */
1468     UINT cbData, /* [in]  Size of metric data array */
1469     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1470 {
1471     char buf[512], *ptr;
1472     UINT ret, needed;
1473     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1474     OUTLINETEXTMETRICA *output = lpOTM;
1475     INT left, len;
1476
1477     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1478         return 0;
1479     if(ret > sizeof(buf))
1480         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1481     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1482
1483     needed = sizeof(OUTLINETEXTMETRICA);
1484     if(lpOTMW->otmpFamilyName)
1485         needed += WideCharToMultiByte(CP_ACP, 0,
1486            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1487                                       NULL, 0, NULL, NULL);
1488     if(lpOTMW->otmpFaceName)
1489         needed += WideCharToMultiByte(CP_ACP, 0,
1490            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1491                                       NULL, 0, NULL, NULL);
1492     if(lpOTMW->otmpStyleName)
1493         needed += WideCharToMultiByte(CP_ACP, 0,
1494            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1495                                       NULL, 0, NULL, NULL);
1496     if(lpOTMW->otmpFullName)
1497         needed += WideCharToMultiByte(CP_ACP, 0,
1498            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1499                                       NULL, 0, NULL, NULL);
1500
1501     if(!lpOTM) {
1502         ret = needed;
1503         goto end;
1504     }
1505
1506     TRACE("needed = %d\n", needed);
1507     if(needed > cbData)
1508         /* Since the supplied buffer isn't big enough, we'll alloc one
1509            that is and memcpy the first cbData bytes into the lpOTM at
1510            the end. */
1511         output = HeapAlloc(GetProcessHeap(), 0, needed);
1512
1513     ret = output->otmSize = min(needed, cbData);
1514     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1515     output->otmFiller = 0;
1516     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1517     output->otmfsSelection = lpOTMW->otmfsSelection;
1518     output->otmfsType = lpOTMW->otmfsType;
1519     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1520     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1521     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1522     output->otmEMSquare = lpOTMW->otmEMSquare;
1523     output->otmAscent = lpOTMW->otmAscent;
1524     output->otmDescent = lpOTMW->otmDescent;
1525     output->otmLineGap = lpOTMW->otmLineGap;
1526     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1527     output->otmsXHeight = lpOTMW->otmsXHeight;
1528     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1529     output->otmMacAscent = lpOTMW->otmMacAscent;
1530     output->otmMacDescent = lpOTMW->otmMacDescent;
1531     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1532     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1533     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1534     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1535     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1536     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1537     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1538     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1539     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1540     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1541
1542
1543     ptr = (char*)(output + 1);
1544     left = needed - sizeof(*output);
1545
1546     if(lpOTMW->otmpFamilyName) {
1547         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1548         len = WideCharToMultiByte(CP_ACP, 0,
1549              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1550                                   ptr, left, NULL, NULL);
1551         left -= len;
1552         ptr += len;
1553     } else
1554         output->otmpFamilyName = 0;
1555
1556     if(lpOTMW->otmpFaceName) {
1557         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1558         len = WideCharToMultiByte(CP_ACP, 0,
1559              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1560                                   ptr, left, NULL, NULL);
1561         left -= len;
1562         ptr += len;
1563     } else
1564         output->otmpFaceName = 0;
1565
1566     if(lpOTMW->otmpStyleName) {
1567         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1568         len = WideCharToMultiByte(CP_ACP, 0,
1569              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1570                                   ptr, left, NULL, NULL);
1571         left -= len;
1572         ptr += len;
1573     } else
1574         output->otmpStyleName = 0;
1575
1576     if(lpOTMW->otmpFullName) {
1577         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1578         len = WideCharToMultiByte(CP_ACP, 0,
1579              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1580                                   ptr, left, NULL, NULL);
1581         left -= len;
1582     } else
1583         output->otmpFullName = 0;
1584
1585     assert(left == 0);
1586
1587     if(output != lpOTM) {
1588         memcpy(lpOTM, output, cbData);
1589         HeapFree(GetProcessHeap(), 0, output);
1590
1591         /* check if the string offsets really fit into the provided size */
1592         /* FIXME: should we check string length as well? */
1593         /* make sure that we don't read/write beyond the provided buffer */
1594         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1595         {
1596             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1597                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1598         }
1599
1600         /* make sure that we don't read/write beyond the provided buffer */
1601         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1602         {
1603             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1604                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1605         }
1606
1607             /* make sure that we don't read/write beyond the provided buffer */
1608         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1609         {
1610             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1611                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1612         }
1613
1614         /* make sure that we don't read/write beyond the provided buffer */
1615         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1616         {
1617             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1618                 lpOTM->otmpFullName = 0; /* doesn't fit */
1619         }
1620     }
1621
1622 end:
1623     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1624         HeapFree(GetProcessHeap(), 0, lpOTMW);
1625
1626     return ret;
1627 }
1628
1629
1630 /***********************************************************************
1631  *           GetOutlineTextMetricsW [GDI32.@]
1632  */
1633 UINT WINAPI GetOutlineTextMetricsW(
1634     HDC hdc,    /* [in]  Handle of device context */
1635     UINT cbData, /* [in]  Size of metric data array */
1636     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1637 {
1638     DC *dc = DC_GetDCPtr( hdc );
1639     OUTLINETEXTMETRICW *output = lpOTM;
1640     UINT ret;
1641
1642     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1643     if(!dc) return 0;
1644
1645     if(dc->gdiFont) {
1646         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1647         if(lpOTM && ret) {
1648             if(ret > cbData) {
1649                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1650                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1651             }
1652
1653 #define WDPTOLP(x) ((x<0)?                                      \
1654                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1655                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1656 #define HDPTOLP(y) ((y<0)?                                      \
1657                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1658                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1659
1660             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1661             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1662             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1663             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1664             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1665             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1666             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1667             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1668             output->otmAscent = HDPTOLP(output->otmAscent);
1669             output->otmDescent = HDPTOLP(output->otmDescent);
1670             output->otmLineGap = HDPTOLP(output->otmLineGap);
1671             output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1672             output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1673             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1674             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1675             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1676             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1677             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1678             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1679             output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1680             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1681             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1682             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1683             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1684             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1685             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1686             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1687             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1688             output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1689             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1690             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1691             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1692 #undef WDPTOLP
1693 #undef HDPTOLP
1694             if(output != lpOTM) {
1695                 memcpy(lpOTM, output, cbData);
1696                 HeapFree(GetProcessHeap(), 0, output);
1697                 ret = cbData;
1698             }
1699         }
1700     }
1701
1702     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1703               but really this should just be a return 0. */
1704
1705         ret = sizeof(*lpOTM);
1706         if (lpOTM) {
1707             if(cbData < ret)
1708                 ret = 0;
1709             else {
1710                 memset(lpOTM, 0, ret);
1711                 lpOTM->otmSize = sizeof(*lpOTM);
1712                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1713                 /*
1714                   Further fill of the structure not implemented,
1715                   Needs real values for the structure members
1716                 */
1717             }
1718         }
1719     }
1720     GDI_ReleaseObj(hdc);
1721     return ret;
1722 }
1723
1724
1725 /***********************************************************************
1726  *           GetCharWidthW      (GDI32.@)
1727  *           GetCharWidth32W    (GDI32.@)
1728  */
1729 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1730                                LPINT buffer )
1731 {
1732     UINT i;
1733     BOOL ret = FALSE;
1734     DC * dc = DC_GetDCPtr( hdc );
1735     if (!dc) return FALSE;
1736
1737     if (dc->gdiFont)
1738         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1739     else if (dc->funcs->pGetCharWidth)
1740         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1741
1742     if (ret)
1743     {
1744         /* convert device units to logical */
1745         for( i = firstChar; i <= lastChar; i++, buffer++ )
1746             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1747         ret = TRUE;
1748     }
1749     GDI_ReleaseObj( hdc );
1750     return ret;
1751 }
1752
1753
1754 /***********************************************************************
1755  *           GetCharWidthA      (GDI32.@)
1756  *           GetCharWidth32A    (GDI32.@)
1757  */
1758 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1759                                LPINT buffer )
1760 {
1761     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1762     LPSTR str;
1763     LPWSTR wstr;
1764     BOOL ret = TRUE;
1765
1766     if(count <= 0) return FALSE;
1767
1768     str = HeapAlloc(GetProcessHeap(), 0, count);
1769     for(i = 0; i < count; i++)
1770         str[i] = (BYTE)(firstChar + i);
1771
1772     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1773
1774     for(i = 0; i < wlen; i++)
1775     {
1776         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1777         {
1778             ret = FALSE;
1779             break;
1780         }
1781         buffer++;
1782     }
1783
1784     HeapFree(GetProcessHeap(), 0, str);
1785     HeapFree(GetProcessHeap(), 0, wstr);
1786
1787     return ret;
1788 }
1789
1790
1791 /***********************************************************************
1792  *           ExtTextOutA    (GDI32.@)
1793  *
1794  * See ExtTextOutW.
1795  */
1796 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1797                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1798 {
1799     INT wlen;
1800     UINT codepage;
1801     LPWSTR p;
1802     BOOL ret;
1803     LPINT lpDxW = NULL;
1804
1805     if (flags & ETO_GLYPH_INDEX)
1806         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1807
1808     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1809
1810     if (lpDx) {
1811         unsigned int i = 0, j = 0;
1812
1813         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1814         while(i < count) {
1815             if(IsDBCSLeadByteEx(codepage, str[i])) {
1816                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1817                 i = i + 2;
1818             } else {
1819                 lpDxW[j++] = lpDx[i];
1820                 i = i + 1;
1821             }
1822         }
1823     }
1824
1825     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1826
1827     HeapFree( GetProcessHeap(), 0, p );
1828     HeapFree( GetProcessHeap(), 0, lpDxW );
1829     return ret;
1830 }
1831
1832
1833 /***********************************************************************
1834  *           ExtTextOutW    (GDI32.@)
1835  *
1836  * Draws text using the currently selected font, background color, and text color.
1837  * 
1838  * 
1839  * PARAMS
1840  *    x,y    [I] coordinates of string
1841  *    flags  [I]
1842  *        ETO_GRAYED - undocumented on MSDN
1843  *        ETO_OPAQUE - use background color for fill the rectangle
1844  *        ETO_CLIPPED - clipping text to the rectangle
1845  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1846  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1847  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1848  *                         Affects BiDi ordering
1849  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1850  *        ETO_PDY - unimplemented
1851  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1852  *                            do not translate numbers into locale representations
1853  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1854  *    lprect [I] dimensions for clipping or/and opaquing
1855  *    str    [I] text string
1856  *    count  [I] number of symbols in string
1857  *    lpDx   [I] optional parameter with distance between drawing characters
1858  *
1859  * RETURNS
1860  *    Success: TRUE
1861  *    Failure: FALSE
1862  */
1863 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1864                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1865 {
1866     BOOL ret = FALSE;
1867     LPWSTR reordered_str = (LPWSTR)str;
1868     WORD *glyphs = NULL;
1869     UINT align = GetTextAlign( hdc );
1870     POINT pt;
1871     TEXTMETRICW tm;
1872     LOGFONTW lf;
1873     double cosEsc, sinEsc;
1874     INT *deltas = NULL, char_extra;
1875     SIZE sz;
1876     RECT rc;
1877     BOOL done_extents = FALSE;
1878     INT width = 0, xwidth = 0, ywidth = 0;
1879     DWORD type;
1880     DC * dc = DC_GetDCUpdate( hdc );
1881     INT breakRem;
1882
1883     if (!dc) return FALSE;
1884
1885     breakRem = dc->breakRem;
1886
1887     if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1888         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1889
1890     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1891     {
1892         GDI_ReleaseObj( hdc );
1893         return ret;
1894     }
1895
1896     type = GetObjectType(hdc);
1897     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1898     {
1899         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1900         GDI_ReleaseObj( hdc );
1901         return ret;
1902     }
1903
1904     if (!lprect)
1905         flags &= ~ETO_CLIPPED;
1906         
1907     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1908     {
1909         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1910
1911         BIDI_Reorder( str, count, GCP_REORDER,
1912                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1913                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1914                       reordered_str, count, NULL );
1915     
1916         flags |= ETO_IGNORELANGUAGE;
1917     }
1918
1919     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1920           lprect, debugstr_wn(str, count), count, lpDx);
1921
1922     if(flags & ETO_GLYPH_INDEX)
1923         glyphs = reordered_str;
1924
1925     if(lprect)
1926         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1927               lprect->bottom);
1928     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1929
1930     if(align & TA_UPDATECP)
1931     {
1932         GetCurrentPositionEx( hdc, &pt );
1933         x = pt.x;
1934         y = pt.y;
1935     }
1936
1937     GetTextMetricsW(hdc, &tm);
1938     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1939
1940     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1941         lf.lfEscapement = 0;
1942
1943     if(lf.lfEscapement != 0)
1944     {
1945         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1946         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1947     }
1948     else
1949     {
1950         cosEsc = 1;
1951         sinEsc = 0;
1952     }
1953
1954     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1955     {
1956         if(!lprect)
1957         {
1958             if(flags & ETO_GLYPH_INDEX)
1959                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1960             else
1961                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1962
1963             done_extents = TRUE;
1964             rc.left = x;
1965             rc.top = y;
1966             rc.right = x + sz.cx;
1967             rc.bottom = y + sz.cy;
1968         }
1969         else
1970         {
1971             rc = *lprect;
1972         }
1973
1974         LPtoDP(hdc, (POINT*)&rc, 2);
1975
1976         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1977         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1978     }
1979
1980     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1981         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1982
1983     if(count == 0)
1984     {
1985         ret = TRUE;
1986         goto done;
1987     }
1988
1989     pt.x = x;
1990     pt.y = y;
1991     LPtoDP(hdc, &pt, 1);
1992     x = pt.x;
1993     y = pt.y;
1994
1995     char_extra = GetTextCharacterExtra(hdc);
1996     if(char_extra || dc->breakExtra || breakRem || lpDx)
1997     {
1998         UINT i;
1999         SIZE tmpsz;
2000         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2001         for(i = 0; i < count; i++)
2002         {
2003             if(lpDx && (flags & ETO_PDY))
2004                 deltas[i] = lpDx[i*2] + char_extra;
2005             else if(lpDx)
2006                 deltas[i] = lpDx[i] + char_extra;
2007             else
2008             {
2009                 if(flags & ETO_GLYPH_INDEX)
2010                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2011                 else
2012                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2013
2014                 deltas[i] = tmpsz.cx;
2015             }
2016             
2017             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2018             {
2019                 deltas[i] = deltas[i] + dc->breakExtra;
2020                 if (breakRem > 0)
2021                 {
2022                     breakRem--;
2023                     deltas[i]++;
2024                 }
2025             }
2026             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2027             width += deltas[i];
2028         }
2029     }
2030     else
2031     {
2032         if(!done_extents)
2033         {
2034             if(flags & ETO_GLYPH_INDEX)
2035                 GetTextExtentPointI(hdc, glyphs, count, &sz);
2036             else
2037                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2038             done_extents = TRUE;
2039         }
2040         width = INTERNAL_XWSTODS(dc, sz.cx);
2041     }
2042     xwidth = width * cosEsc;
2043     ywidth = width * sinEsc;
2044
2045     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2046     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2047     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2048     {
2049     case TA_LEFT:
2050         if (align & TA_UPDATECP)
2051         {
2052             pt.x = x + xwidth;
2053             pt.y = y - ywidth;
2054             DPtoLP(hdc, &pt, 1);
2055             MoveToEx(hdc, pt.x, pt.y, NULL);
2056         }
2057         break;
2058
2059     case TA_CENTER:
2060         x -= xwidth / 2;
2061         y += ywidth / 2;
2062         break;
2063
2064     case TA_RIGHT:
2065         x -= xwidth;
2066         y += ywidth;
2067         if (align & TA_UPDATECP)
2068         {
2069             pt.x = x;
2070             pt.y = y;
2071             DPtoLP(hdc, &pt, 1);
2072             MoveToEx(hdc, pt.x, pt.y, NULL);
2073         }
2074         break;
2075     }
2076
2077     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2078     {
2079     case TA_TOP:
2080         y += tm.tmAscent * cosEsc;
2081         x += tm.tmAscent * sinEsc;
2082         break;
2083
2084     case TA_BOTTOM:
2085         y -= tm.tmDescent * cosEsc;
2086         x -= tm.tmDescent * sinEsc;
2087         break;
2088
2089     case TA_BASELINE:
2090         break;
2091     }
2092
2093     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2094     {
2095         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2096         {
2097             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2098                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2099             {
2100                 RECT rc;
2101                 rc.left = x;
2102                 rc.right = x + width;
2103                 rc.top = y - tm.tmAscent;
2104                 rc.bottom = y + tm.tmDescent;
2105                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2106             }
2107         }
2108     }
2109
2110     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2111     {
2112         HFONT orig_font = dc->hFont, cur_font;
2113         UINT glyph;
2114         INT span = 0, *offsets = NULL, i;
2115
2116         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2117         for(i = 0; i < count; i++)
2118         {
2119             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2120             if(cur_font != dc->hFont)
2121             {
2122                 if(!offsets)
2123                 {
2124                     int j;
2125                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2126                     offsets[0] = 0;
2127                     if(!deltas)
2128                     {
2129                         SIZE tmpsz;
2130                         for(j = 1; j < count; j++)
2131                         {
2132                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2133                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2134                         }
2135                     }
2136                     else
2137                     {
2138                         for(j = 1; j < count; j++)
2139                             offsets[j] = offsets[j-1] + deltas[j];
2140                     }
2141                 }
2142                 if(span)
2143                 {
2144                     if (PATH_IsPathOpen(dc->path))
2145                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2146                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2147                                               glyphs, span, deltas ? deltas + i - span : NULL);
2148                     else
2149                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2150                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2151                                            glyphs, span, deltas ? deltas + i - span : NULL);
2152                     span = 0;
2153                 }
2154                 SelectObject(hdc, cur_font);
2155             }
2156             glyphs[span++] = glyph;
2157
2158             if(i == count - 1)
2159             {
2160                 if (PATH_IsPathOpen(dc->path))
2161                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2162                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
2163                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2164                                           glyphs, span, deltas ? deltas + count - span : NULL);
2165                 else
2166                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2167                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
2168                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2169                                              glyphs, span, deltas ? deltas + count - span : NULL);
2170                 SelectObject(hdc, orig_font);
2171                 HeapFree(GetProcessHeap(), 0, offsets);
2172            }
2173         }
2174     }
2175     else
2176     {
2177         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2178         {
2179             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2180             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2181             flags |= ETO_GLYPH_INDEX;
2182         }
2183
2184         if (PATH_IsPathOpen(dc->path))
2185             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2186                                   glyphs ? glyphs : reordered_str, count, deltas);
2187         else
2188             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2189                                      glyphs ? glyphs : reordered_str, count, deltas);
2190     }
2191
2192 done:
2193     HeapFree(GetProcessHeap(), 0, deltas);
2194     if(glyphs != reordered_str)
2195         HeapFree(GetProcessHeap(), 0, glyphs);
2196     if(reordered_str != str)
2197         HeapFree(GetProcessHeap(), 0, reordered_str);
2198
2199     GDI_ReleaseObj( hdc );
2200
2201     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2202     {
2203         int underlinePos, strikeoutPos;
2204         int underlineWidth, strikeoutWidth;
2205         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2206         OUTLINETEXTMETRICW* otm = NULL;
2207
2208         if(!size)
2209         {
2210             underlinePos = 0;
2211             underlineWidth = tm.tmAscent / 20 + 1;
2212             strikeoutPos = tm.tmAscent / 2;
2213             strikeoutWidth = underlineWidth;
2214         }
2215         else
2216         {
2217             otm = HeapAlloc(GetProcessHeap(), 0, size);
2218             GetOutlineTextMetricsW(hdc, size, otm);
2219             underlinePos = otm->otmsUnderscorePosition;
2220             underlineWidth = otm->otmsUnderscoreSize;
2221             strikeoutPos = otm->otmsStrikeoutPosition;
2222             strikeoutWidth = otm->otmsStrikeoutSize;
2223             HeapFree(GetProcessHeap(), 0, otm);
2224         }
2225
2226         if (PATH_IsPathOpen(dc->path))
2227         {
2228             POINT pts[5];
2229             HPEN hpen;
2230             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2231
2232             hbrush = SelectObject(hdc, hbrush);
2233             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2234
2235             if (lf.lfUnderline)
2236             {
2237                 pts[0].x = x - underlinePos * sinEsc;
2238                 pts[0].y = y - underlinePos * cosEsc;
2239                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2240                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2241                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2242                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2243                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2244                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2245                 pts[4].x = pts[0].x;
2246                 pts[4].y = pts[0].y;
2247                 DPtoLP(hdc, pts, 5);
2248                 Polygon(hdc, pts, 5);
2249             }
2250
2251             if (lf.lfStrikeOut)
2252             {
2253                 pts[0].x = x - strikeoutPos * sinEsc;
2254                 pts[0].y = y - strikeoutPos * cosEsc;
2255                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2256                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2257                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2258                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2259                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2260                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2261                 pts[4].x = pts[0].x;
2262                 pts[4].y = pts[0].y;
2263                 DPtoLP(hdc, pts, 5);
2264                 Polygon(hdc, pts, 5);
2265             }
2266
2267             SelectObject(hdc, hpen);
2268             hbrush = SelectObject(hdc, hbrush);
2269             DeleteObject(hbrush);
2270         }
2271         else
2272         {
2273             POINT pts[2], oldpt;
2274             HPEN hpen;
2275
2276             if (lf.lfUnderline)
2277             {
2278                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2279                 hpen = SelectObject(hdc, hpen);
2280                 pts[0].x = x;
2281                 pts[0].y = y;
2282                 pts[1].x = x + xwidth;
2283                 pts[1].y = y - ywidth;
2284                 DPtoLP(hdc, pts, 2);
2285                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2286                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2287                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2288                 DeleteObject(SelectObject(hdc, hpen));
2289             }
2290
2291             if (lf.lfStrikeOut)
2292             {
2293                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2294                 hpen = SelectObject(hdc, hpen);
2295                 pts[0].x = x;
2296                 pts[0].y = y;
2297                 pts[1].x = x + xwidth;
2298                 pts[1].y = y - ywidth;
2299                 DPtoLP(hdc, pts, 2);
2300                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2301                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2302                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2303                 DeleteObject(SelectObject(hdc, hpen));
2304             }
2305         }
2306     }
2307
2308     return ret;
2309 }
2310
2311
2312 /***********************************************************************
2313  *           TextOutA    (GDI32.@)
2314  */
2315 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2316 {
2317     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2318 }
2319
2320
2321 /***********************************************************************
2322  *           TextOutW    (GDI32.@)
2323  */
2324 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2325 {
2326     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2327 }
2328
2329
2330 /***********************************************************************
2331  *              PolyTextOutA (GDI32.@)
2332  *
2333  * See PolyTextOutW.
2334  */
2335 BOOL WINAPI PolyTextOutA ( HDC hdc,               /* [in] Handle to device context */
2336                            PPOLYTEXTA pptxt,      /* [in] Array of strings */
2337                            INT cStrings )         /* [in] Number of strings in array */
2338 {
2339     for (; cStrings>0; cStrings--, pptxt++)
2340         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2341             return FALSE;
2342     return TRUE;
2343 }
2344
2345
2346
2347 /***********************************************************************
2348  *              PolyTextOutW (GDI32.@)
2349  *
2350  * Draw several Strings
2351  *
2352  * RETURNS
2353  *  TRUE:  Success.
2354  *  FALSE: Failure.
2355  */
2356 BOOL WINAPI PolyTextOutW ( HDC hdc,               /* [in] Handle to device context */
2357                            PPOLYTEXTW pptxt,      /* [in] Array of strings */
2358                            INT cStrings )         /* [in] Number of strings in array */
2359 {
2360     for (; cStrings>0; cStrings--, pptxt++)
2361         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2362             return FALSE;
2363     return TRUE;
2364 }
2365
2366
2367 /* FIXME: all following APIs ******************************************/
2368
2369
2370 /***********************************************************************
2371  *           SetMapperFlags    (GDI32.@)
2372  */
2373 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2374 {
2375     DC *dc = DC_GetDCPtr( hDC );
2376     DWORD ret = 0;
2377     if(!dc) return 0;
2378     if(dc->funcs->pSetMapperFlags)
2379     {
2380         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2381         /* FIXME: ret is just a success flag, we should return a proper value */
2382     }
2383     else
2384         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2385     GDI_ReleaseObj( hDC );
2386     return ret;
2387 }
2388
2389 /***********************************************************************
2390  *          GetAspectRatioFilterEx  (GDI.486)
2391  */
2392 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2393 {
2394   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2395   return FALSE;
2396 }
2397
2398 /***********************************************************************
2399  *          GetAspectRatioFilterEx  (GDI32.@)
2400  */
2401 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2402 {
2403   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2404   return FALSE;
2405 }
2406
2407
2408 /***********************************************************************
2409  *           GetCharABCWidthsA   (GDI32.@)
2410  *
2411  * See GetCharABCWidthsW.
2412  */
2413 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2414                                   LPABC abc )
2415 {
2416     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2417     LPSTR str;
2418     LPWSTR wstr;
2419     BOOL ret = TRUE;
2420
2421     if(count <= 0) return FALSE;
2422
2423     str = HeapAlloc(GetProcessHeap(), 0, count);
2424     for(i = 0; i < count; i++)
2425         str[i] = (BYTE)(firstChar + i);
2426
2427     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2428
2429     for(i = 0; i < wlen; i++)
2430     {
2431         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2432         {
2433             ret = FALSE;
2434             break;
2435         }
2436         abc++;
2437     }
2438
2439     HeapFree(GetProcessHeap(), 0, str);
2440     HeapFree(GetProcessHeap(), 0, wstr);
2441
2442     return ret;
2443 }
2444
2445
2446 /******************************************************************************
2447  * GetCharABCWidthsW [GDI32.@]
2448  *
2449  * Retrieves widths of characters in range.
2450  *
2451  * PARAMS
2452  *    hdc       [I] Handle of device context
2453  *    firstChar [I] First character in range to query
2454  *    lastChar  [I] Last character in range to query
2455  *    abc       [O] Address of character-width structure
2456  *
2457  * NOTES
2458  *    Only works with TrueType fonts
2459  *
2460  * RETURNS
2461  *    Success: TRUE
2462  *    Failure: FALSE
2463  */
2464 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2465                                    LPABC abc )
2466 {
2467     DC *dc = DC_GetDCPtr(hdc);
2468     unsigned int i;
2469     BOOL ret = FALSE;
2470
2471     if (!dc) return FALSE;
2472
2473     if(dc->gdiFont)
2474         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2475     else
2476         FIXME(": stub\n");
2477
2478     if (ret)
2479     {
2480         /* convert device units to logical */
2481         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2482             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2483             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2484             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2485         }
2486         ret = TRUE;
2487     }
2488
2489     GDI_ReleaseObj(hdc);
2490     return ret;
2491 }
2492
2493
2494 /******************************************************************************
2495  * GetCharABCWidthsI [GDI32.@]
2496  *
2497  * Retrieves widths of characters in range.
2498  *
2499  * PARAMS
2500  *    hdc       [I] Handle of device context
2501  *    firstChar [I] First glyphs in range to query
2502  *    count     [I] Last glyphs in range to query
2503  *    pgi       [i] Array of glyphs to query
2504  *    abc       [O] Address of character-width structure
2505  *
2506  * NOTES
2507  *    Only works with TrueType fonts
2508  *
2509  * RETURNS
2510  *    Success: TRUE
2511  *    Failure: FALSE
2512  */
2513 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2514                                LPWORD pgi, LPABC abc)
2515 {
2516     DC *dc = DC_GetDCPtr(hdc);
2517     unsigned int i;
2518     BOOL ret = FALSE;
2519
2520     if (!dc) return FALSE;
2521
2522     if(dc->gdiFont)
2523         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2524     else
2525         FIXME(": stub\n");
2526
2527     if (ret)
2528     {
2529         /* convert device units to logical */
2530         for( i = 0; i < count; i++, abc++ ) {
2531             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2532             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2533             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2534         }
2535         ret = TRUE;
2536     }
2537
2538     GDI_ReleaseObj(hdc);
2539     return ret;
2540 }
2541
2542
2543 /***********************************************************************
2544  *           GetGlyphOutlineA    (GDI32.@)
2545  */
2546 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2547                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2548                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2549 {
2550     LPWSTR p = NULL;
2551     DWORD ret;
2552     UINT c;
2553
2554     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2555         int len;
2556         char mbchs[2];
2557         if(uChar > 0xff) { /* but, 2 bytes character only */
2558             len = 2;
2559             mbchs[0] = (uChar & 0xff00) >> 8;
2560             mbchs[1] = (uChar & 0xff);
2561         } else {
2562             len = 1;
2563             mbchs[0] = (uChar & 0xff);
2564         }
2565         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2566         c = p[0];
2567     } else
2568         c = uChar;
2569     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2570                            lpmat2);
2571     HeapFree(GetProcessHeap(), 0, p);
2572     return ret;
2573 }
2574
2575 /***********************************************************************
2576  *           GetGlyphOutlineW    (GDI32.@)
2577  */
2578 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2579                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2580                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2581 {
2582     DC *dc = DC_GetDCPtr(hdc);
2583     DWORD ret;
2584
2585     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2586           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2587
2588     if(!dc) return GDI_ERROR;
2589
2590     if(dc->gdiFont)
2591       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2592                                    cbBuffer, lpBuffer, lpmat2);
2593     else
2594       ret = GDI_ERROR;
2595
2596     GDI_ReleaseObj(hdc);
2597     return ret;
2598 }
2599
2600
2601 /***********************************************************************
2602  *           CreateScalableFontResourceA   (GDI32.@)
2603  */
2604 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2605                                              LPCSTR lpszResourceFile,
2606                                              LPCSTR lpszFontFile,
2607                                              LPCSTR lpszCurrentPath )
2608 {
2609     HANDLE f;
2610
2611     /* fHidden=1 - only visible for the calling app, read-only, not
2612      * enumbered with EnumFonts/EnumFontFamilies
2613      * lpszCurrentPath can be NULL
2614      */
2615     FIXME("(%d,%s,%s,%s): stub\n",
2616           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2617           debugstr_a(lpszCurrentPath) );
2618
2619     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2620     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2621         CloseHandle(f);
2622         SetLastError(ERROR_FILE_EXISTS);
2623         return FALSE;
2624     }
2625     return FALSE; /* create failed */
2626 }
2627
2628 /***********************************************************************
2629  *           CreateScalableFontResourceW   (GDI32.@)
2630  */
2631 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2632                                              LPCWSTR lpszResourceFile,
2633                                              LPCWSTR lpszFontFile,
2634                                              LPCWSTR lpszCurrentPath )
2635 {
2636     FIXME("(%d,%p,%p,%p): stub\n",
2637           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2638     return FALSE; /* create failed */
2639 }
2640
2641 /*************************************************************************
2642  *             GetKerningPairsA   (GDI32.@)
2643  */
2644 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2645                                LPKERNINGPAIR kern_pairA )
2646 {
2647     INT charset;
2648     CHARSETINFO csi;
2649     CPINFO cpi;
2650     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2651     KERNINGPAIR *kern_pairW;
2652
2653     if (!cPairs && kern_pairA)
2654     {
2655         SetLastError(ERROR_INVALID_PARAMETER);
2656         return 0;
2657     }
2658
2659     charset = GetTextCharset(hDC);
2660     if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2661     {
2662         FIXME("Can't find codepage for charset %d\n", charset);
2663         return 0;
2664     }
2665     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2666      * to fail on an invalid character for CP_SYMBOL.
2667      */
2668     cpi.DefaultChar[0] = 0;
2669     if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2670     {
2671         FIXME("Can't find codepage %u info\n", csi.ciACP);
2672         return 0;
2673     }
2674     TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2675
2676     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2677     if (!total_kern_pairs) return 0;
2678
2679     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2680     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2681
2682     for (i = 0; i < total_kern_pairs; i++)
2683     {
2684         char first, second;
2685
2686         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2687             continue;
2688
2689         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2690             continue;
2691
2692         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2693             continue;
2694
2695         if (kern_pairA)
2696         {
2697             if (kern_pairs_copied >= cPairs) break;
2698
2699             kern_pairA->wFirst = (BYTE)first;
2700             kern_pairA->wSecond = (BYTE)second;
2701             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2702             kern_pairA++;
2703         }
2704         kern_pairs_copied++;
2705     }
2706
2707     HeapFree(GetProcessHeap(), 0, kern_pairW);
2708
2709     return kern_pairs_copied;
2710 }
2711
2712 /*************************************************************************
2713  *             GetKerningPairsW   (GDI32.@)
2714  */
2715 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2716                                  LPKERNINGPAIR lpKerningPairs )
2717 {
2718     DC *dc;
2719     DWORD ret = 0;
2720
2721     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2722
2723     if (!cPairs && lpKerningPairs)
2724     {
2725         SetLastError(ERROR_INVALID_PARAMETER);
2726         return 0;
2727     }
2728
2729     dc = DC_GetDCPtr(hDC);
2730     if (!dc) return 0;
2731
2732     if (dc->gdiFont)
2733         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2734
2735     GDI_ReleaseObj(hDC);
2736     return ret;
2737 }
2738
2739 /*************************************************************************
2740  * TranslateCharsetInfo [GDI32.@]
2741  *
2742  * Fills a CHARSETINFO structure for a character set, code page, or
2743  * font. This allows making the correspondance between different labelings
2744  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2745  * of the same encoding.
2746  *
2747  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2748  * only one codepage should be set in *lpSrc.
2749  *
2750  * RETURNS
2751  *   TRUE on success, FALSE on failure.
2752  *
2753  */
2754 BOOL WINAPI TranslateCharsetInfo(
2755   LPDWORD lpSrc, /* [in]
2756        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2757        if flags == TCI_SRCCHARSET: a character set value
2758        if flags == TCI_SRCCODEPAGE: a code page value
2759                  */
2760   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2761   DWORD flags /* [in] determines interpretation of lpSrc */)
2762 {
2763     int index = 0;
2764     switch (flags) {
2765     case TCI_SRCFONTSIG:
2766         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2767       break;
2768     case TCI_SRCCODEPAGE:
2769       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2770       break;
2771     case TCI_SRCCHARSET:
2772       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2773       break;
2774     default:
2775       return FALSE;
2776     }
2777     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2778     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2779     return TRUE;
2780 }
2781
2782 /*************************************************************************
2783  *             GetFontLanguageInfo   (GDI32.@)
2784  */
2785 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2786 {
2787         FONTSIGNATURE fontsig;
2788         static const DWORD GCP_DBCS_MASK=0x003F0000,
2789                 GCP_DIACRITIC_MASK=0x00000000,
2790                 FLI_GLYPHS_MASK=0x00000000,
2791                 GCP_GLYPHSHAPE_MASK=0x00000040,
2792                 GCP_KASHIDA_MASK=0x00000000,
2793                 GCP_LIGATE_MASK=0x00000000,
2794                 GCP_USEKERNING_MASK=0x00000000,
2795                 GCP_REORDER_MASK=0x00000060;
2796
2797         DWORD result=0;
2798
2799         GetTextCharsetInfo( hdc, &fontsig, 0 );
2800         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2801
2802         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2803                 result|=GCP_DBCS;
2804
2805         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2806                 result|=GCP_DIACRITIC;
2807
2808         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2809                 result|=FLI_GLYPHS;
2810
2811         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2812                 result|=GCP_GLYPHSHAPE;
2813
2814         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2815                 result|=GCP_KASHIDA;
2816
2817         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2818                 result|=GCP_LIGATE;
2819
2820         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2821                 result|=GCP_USEKERNING;
2822
2823         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2824         if( GetTextAlign( hdc) & TA_RTLREADING )
2825             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2826                     result|=GCP_REORDER;
2827
2828         return result;
2829 }
2830
2831
2832 /*************************************************************************
2833  * GetFontData [GDI32.@]
2834  *
2835  * Retrieve data for TrueType font.
2836  *
2837  * RETURNS
2838  *
2839  * success: Number of bytes returned
2840  * failure: GDI_ERROR
2841  *
2842  * NOTES
2843  *
2844  * Calls SetLastError()
2845  *
2846  */
2847 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2848     LPVOID buffer, DWORD length)
2849 {
2850     DC *dc = DC_GetDCPtr(hdc);
2851     DWORD ret = GDI_ERROR;
2852
2853     if(!dc) return GDI_ERROR;
2854
2855     if(dc->gdiFont)
2856       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2857
2858     GDI_ReleaseObj(hdc);
2859     return ret;
2860 }
2861
2862 /*************************************************************************
2863  * GetGlyphIndicesA [GDI32.@]
2864  */
2865 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2866                               LPWORD pgi, DWORD flags)
2867 {
2868     DWORD ret;
2869     WCHAR *lpstrW;
2870     INT countW;
2871
2872     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2873           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2874
2875     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2876     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2877     HeapFree(GetProcessHeap(), 0, lpstrW);
2878
2879     return ret;
2880 }
2881
2882 /*************************************************************************
2883  * GetGlyphIndicesW [GDI32.@]
2884  */
2885 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2886                               LPWORD pgi, DWORD flags)
2887 {
2888     DC *dc = DC_GetDCPtr(hdc);
2889     DWORD ret = GDI_ERROR;
2890
2891     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2892           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2893
2894     if(!dc) return GDI_ERROR;
2895
2896     if(dc->gdiFont)
2897         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2898
2899     GDI_ReleaseObj(hdc);
2900     return ret;
2901 }
2902
2903 /*************************************************************************
2904  * GetCharacterPlacementA [GDI32.@]
2905  *
2906  * See GetCharacterPlacementW.
2907  *
2908  * NOTES:
2909  *  the web browser control of ie4 calls this with dwFlags=0
2910  */
2911 DWORD WINAPI
2912 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2913                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2914                          DWORD dwFlags)
2915 {
2916     WCHAR *lpStringW;
2917     INT uCountW;
2918     GCP_RESULTSW resultsW;
2919     DWORD ret;
2920     UINT font_cp;
2921
2922     TRACE("%s, %d, %d, 0x%08x\n",
2923           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2924
2925     /* both structs are equal in size */
2926     memcpy(&resultsW, lpResults, sizeof(resultsW));
2927
2928     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2929     if(lpResults->lpOutString)
2930         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2931
2932     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2933
2934     lpResults->nGlyphs = resultsW.nGlyphs;
2935     lpResults->nMaxFit = resultsW.nMaxFit;
2936
2937     if(lpResults->lpOutString) {
2938         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2939                             lpResults->lpOutString, uCount, NULL, NULL );
2940     }
2941
2942     HeapFree(GetProcessHeap(), 0, lpStringW);
2943     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2944
2945     return ret;
2946 }
2947
2948 /*************************************************************************
2949  * GetCharacterPlacementW [GDI32.@]
2950  *
2951  *   Retrieve information about a string. This includes the width, reordering,
2952  *   Glyphing and so on.
2953  *
2954  * RETURNS
2955  *
2956  *   The width and height of the string if successful, 0 if failed.
2957  *
2958  * BUGS
2959  *
2960  *   All flags except GCP_REORDER are not yet implemented.
2961  *   Reordering is not 100% complient to the Windows BiDi method.
2962  *   Caret positioning is not yet implemented for BiDi.
2963  *   Classes are not yet implemented.
2964  *
2965  */
2966 DWORD WINAPI
2967 GetCharacterPlacementW(
2968                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2969                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2970                 INT uCount,             /* [in] Number of WORDS in string. */
2971                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2972                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2973                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2974                 )
2975 {
2976     DWORD ret=0;
2977     SIZE size;
2978     UINT i, nSet;
2979
2980     TRACE("%s, %d, %d, 0x%08x\n",
2981           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2982
2983     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2984           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2985             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2986             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2987             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2988
2989     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2990     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2991     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2992         FIXME("Caret positions for complex scripts not implemented\n");
2993
2994         nSet = (UINT)uCount;
2995         if(nSet > lpResults->nGlyphs)
2996                 nSet = lpResults->nGlyphs;
2997
2998         /* return number of initialized fields */
2999         lpResults->nGlyphs = nSet;
3000
3001         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
3002         {
3003                 /* Treat the case where no special handling was requested in a fastpath way */
3004                 /* copy will do if the GCP_REORDER flag is not set */
3005                 if(lpResults->lpOutString)
3006                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3007
3008                 if(lpResults->lpOrder)
3009                 {
3010                         for(i = 0; i < nSet; i++)
3011                                 lpResults->lpOrder[i] = i;
3012                 }
3013         } else
3014         {
3015             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3016                           nSet, lpResults->lpOrder );
3017         }
3018
3019         /* FIXME: Will use the placement chars */
3020         if (lpResults->lpDx)
3021         {
3022                 int c;
3023                 for (i = 0; i < nSet; i++)
3024                 {
3025                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3026                                 lpResults->lpDx[i]= c;
3027                 }
3028         }
3029
3030     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3031     {
3032         int pos = 0;
3033        
3034         lpResults->lpCaretPos[0] = 0;
3035         for (i = 1; i < nSet; i++)
3036             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3037                 lpResults->lpCaretPos[i] = (pos += size.cx);
3038     }
3039    
3040     if(lpResults->lpGlyphs)
3041         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3042
3043     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3044       ret = MAKELONG(size.cx, size.cy);
3045
3046     return ret;
3047 }
3048
3049 /*************************************************************************
3050  *      GetCharABCWidthsFloatA [GDI32.@]
3051  *
3052  * See GetCharABCWidthsFloatW.
3053  */
3054 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3055 {
3056     INT i, wlen, count = (INT)(last - first + 1);
3057     LPSTR str;
3058     LPWSTR wstr;
3059     BOOL ret = TRUE;
3060
3061     if (count <= 0) return FALSE;
3062
3063     str = HeapAlloc(GetProcessHeap(), 0, count);
3064
3065     for(i = 0; i < count; i++)
3066         str[i] = (BYTE)(first + i);
3067
3068     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3069
3070     for (i = 0; i < wlen; i++)
3071     {
3072         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3073         {
3074             ret = FALSE;
3075             break;
3076         }
3077         abcf++;
3078     }
3079
3080     HeapFree( GetProcessHeap(), 0, str );
3081     HeapFree( GetProcessHeap(), 0, wstr );
3082
3083     return ret;
3084 }
3085
3086 /*************************************************************************
3087  *      GetCharABCWidthsFloatW [GDI32.@]
3088  *
3089  * Retrieves widths of a range of characters.
3090  *
3091  * PARAMS
3092  *    hdc   [I] Handle to device context.
3093  *    first [I] First character in range to query.
3094  *    last  [I] Last character in range to query.
3095  *    abcf  [O] Array of LPABCFLOAT structures.
3096  *
3097  * RETURNS
3098  *    Success: TRUE
3099  *    Failure: FALSE
3100  *
3101  * BUGS
3102  *    Only works with TrueType fonts. It also doesn't return real
3103  *    floats but converted integers because it's implemented on
3104  *    top of GetCharABCWidthsW.
3105  */
3106 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3107 {
3108     ABC *abc;
3109     unsigned int i, size = sizeof(ABC) * (last - first + 1);
3110     BOOL ret;
3111
3112     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3113
3114     abc = HeapAlloc( GetProcessHeap(), 0, size );
3115     if (!abc) return FALSE;
3116
3117     ret = GetCharABCWidthsW( hdc, first, last, abc );
3118     if (ret)
3119     {
3120         for (i = first; i <= last; i++, abc++, abcf++)
3121         {
3122             abcf->abcfA = abc->abcA;
3123             abcf->abcfB = abc->abcB;
3124             abcf->abcfC = abc->abcC;
3125         }
3126     }
3127     HeapFree( GetProcessHeap(), 0, abc );
3128     return ret;
3129 }
3130
3131 /*************************************************************************
3132  *      GetCharWidthFloatA [GDI32.@]
3133  */
3134 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3135                                     UINT iLastChar, PFLOAT pxBuffer)
3136 {
3137     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3138     return 0;
3139 }
3140
3141 /*************************************************************************
3142  *      GetCharWidthFloatW [GDI32.@]
3143  */
3144 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3145                                     UINT iLastChar, PFLOAT pxBuffer)
3146 {
3147     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3148     return 0;
3149 }
3150
3151
3152 /***********************************************************************
3153  *                                                                     *
3154  *           Font Resource API                                         *
3155  *                                                                     *
3156  ***********************************************************************/
3157
3158 /***********************************************************************
3159  *           AddFontResourceA    (GDI32.@)
3160  */
3161 INT WINAPI AddFontResourceA( LPCSTR str )
3162 {
3163     return AddFontResourceExA( str, 0, NULL);
3164 }
3165
3166 /***********************************************************************
3167  *           AddFontResourceW    (GDI32.@)
3168  */
3169 INT WINAPI AddFontResourceW( LPCWSTR str )
3170 {
3171     return AddFontResourceExW(str, 0, NULL);
3172 }
3173
3174
3175 /***********************************************************************
3176  *           AddFontResourceExA    (GDI32.@)
3177  */
3178 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3179 {
3180     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3181     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3182     INT ret;
3183
3184     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3185     ret = AddFontResourceExW(strW, fl, pdv);
3186     HeapFree(GetProcessHeap(), 0, strW);
3187     return ret;
3188 }
3189
3190 /***********************************************************************
3191  *           AddFontResourceExW    (GDI32.@)
3192  */
3193 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3194 {
3195     return WineEngAddFontResourceEx(str, fl, pdv);
3196 }
3197
3198 /***********************************************************************
3199  *           RemoveFontResourceA    (GDI32.@)
3200  */
3201 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3202 {
3203     return RemoveFontResourceExA(str, 0, 0);
3204 }
3205
3206 /***********************************************************************
3207  *           RemoveFontResourceW    (GDI32.@)
3208  */
3209 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3210 {
3211     return RemoveFontResourceExW(str, 0, 0);
3212 }
3213
3214 /***********************************************************************
3215  *           AddFontMemResourceEx    (GDI32.@)
3216  */
3217 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3218 {
3219     FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3220     return NULL;
3221 }
3222
3223 /***********************************************************************
3224  *           RemoveFontResourceExA    (GDI32.@)
3225  */
3226 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3227 {
3228     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3229     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3230     INT ret;
3231
3232     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3233     ret = RemoveFontResourceExW(strW, fl, pdv);
3234     HeapFree(GetProcessHeap(), 0, strW);
3235     return ret;
3236 }
3237
3238 /***********************************************************************
3239  *           RemoveFontResourceExW    (GDI32.@)
3240  */
3241 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3242 {
3243     return WineEngRemoveFontResourceEx(str, fl, pdv);
3244 }
3245
3246 /***********************************************************************
3247  *           GetTextCharset    (GDI32.@)
3248  */
3249 UINT WINAPI GetTextCharset(HDC hdc)
3250 {
3251     /* MSDN docs say this is equivalent */
3252     return GetTextCharsetInfo(hdc, NULL, 0);
3253 }
3254
3255 /***********************************************************************
3256  *           GetTextCharsetInfo    (GDI32.@)
3257  */
3258 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3259 {
3260     UINT ret = DEFAULT_CHARSET;
3261     DC *dc = DC_GetDCPtr(hdc);
3262
3263     if (dc)
3264     {
3265         if (dc->gdiFont)
3266             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3267
3268         GDI_ReleaseObj(hdc);
3269     }
3270
3271     if (ret == DEFAULT_CHARSET && fs)
3272         memset(fs, 0, sizeof(FONTSIGNATURE));
3273     return ret;
3274 }
3275
3276 /***********************************************************************
3277  *           GdiGetCharDimensions    (GDI32.@)
3278  *
3279  * Gets the average width of the characters in the English alphabet.
3280  *
3281  * PARAMS
3282  *  hdc    [I] Handle to the device context to measure on.
3283  *  lptm   [O] Pointer to memory to store the text metrics into.
3284  *  height [O] On exit, the maximum height of characters in the English alphabet.
3285  *
3286  * RETURNS
3287  *  The average width of characters in the English alphabet.
3288  *
3289  * NOTES
3290  *  This function is used by the dialog manager to get the size of a dialog
3291  *  unit. It should also be used by other pieces of code that need to know
3292  *  the size of a dialog unit in logical units without having access to the
3293  *  window handle of the dialog.
3294  *  Windows caches the font metrics from this function, but we don't and
3295  *  there doesn't appear to be an immediate advantage to do so.
3296  *
3297  * SEE ALSO
3298  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3299  */
3300 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3301 {
3302     SIZE sz;
3303     static const WCHAR alphabet[] = {
3304         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3305         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3306         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3307
3308     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3309
3310     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3311
3312     if (height) *height = sz.cy;
3313     return (sz.cx / 26 + 1) / 2;
3314 }
3315
3316 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3317 {
3318     FIXME("(%d): stub\n", fEnableEUDC);
3319     return FALSE;
3320 }
3321
3322 /***********************************************************************
3323  *           GetCharWidthI    (GDI32.@)
3324  *
3325  * Retrieve widths of characters.
3326  *
3327  * PARAMS
3328  *  hdc    [I] Handle to a device context.
3329  *  first  [I] First glyph in range to query.
3330  *  count  [I] Number of glyph indices to query.
3331  *  glyphs [I] Array of glyphs to query.
3332  *  buffer [O] Buffer to receive character widths.
3333  *
3334  * NOTES
3335  *  Only works with TrueType fonts.
3336  *
3337  * RETURNS
3338  *  Success: TRUE
3339  *  Failure: FALSE
3340  */
3341 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3342 {
3343     ABC *abc;
3344     unsigned int i;
3345
3346     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3347
3348     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3349         return FALSE;
3350
3351     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3352     {
3353         HeapFree(GetProcessHeap(), 0, abc);
3354         return FALSE;
3355     }
3356
3357     for (i = 0; i < count; i++)
3358         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3359
3360     HeapFree(GetProcessHeap(), 0, abc);
3361     return TRUE;
3362 }
3363
3364 /***********************************************************************
3365  *           GetFontUnicodeRanges    (GDI32.@)
3366  *
3367  *  Retrieve a list of supported Unicode characters in a font.
3368  *
3369  *  PARAMS
3370  *   hdc  [I] Handle to a device context.
3371  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3372  *
3373  *  RETURNS
3374  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3375  *   Failure: 0
3376  *
3377  */
3378 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3379 {
3380     return WineEngGetFontUnicodeRanges(hdc, lpgs);
3381 }