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