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