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