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