wined3d: Add the bulk of the GLSL string generation functions.
[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 (!lprect)
1753         flags &= ~ETO_CLIPPED;
1754         
1755     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1756     {
1757         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1758
1759         BIDI_Reorder( str, count, GCP_REORDER,
1760                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1761                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1762                       reordered_str, count, NULL );
1763     
1764         flags |= ETO_IGNORELANGUAGE;
1765     }
1766
1767     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1768           lprect, debugstr_wn(str, count), count, lpDx);
1769
1770     if(flags & ETO_GLYPH_INDEX)
1771         glyphs = reordered_str;
1772
1773     if(lprect)
1774         TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1775               lprect->bottom);
1776     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1777
1778     if(align & TA_UPDATECP)
1779     {
1780         GetCurrentPositionEx( hdc, &pt );
1781         x = pt.x;
1782         y = pt.y;
1783     }
1784
1785     GetTextMetricsW(hdc, &tm);
1786     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1787
1788     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1789         lf.lfEscapement = 0;
1790
1791     if(lf.lfEscapement != 0)
1792     {
1793         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1794         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1795     }
1796     else
1797     {
1798         cosEsc = 1;
1799         sinEsc = 0;
1800     }
1801
1802     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1803     {
1804         if(!lprect)
1805         {
1806             if(flags & ETO_GLYPH_INDEX)
1807                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1808             else
1809                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1810
1811             done_extents = TRUE;
1812             rc.left = x;
1813             rc.top = y;
1814             rc.right = x + sz.cx;
1815             rc.bottom = y + sz.cy;
1816         }
1817         else
1818         {
1819             rc = *lprect;
1820         }
1821
1822         LPtoDP(hdc, (POINT*)&rc, 2);
1823
1824         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1825         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1826     }
1827
1828     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1829         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1830
1831     if(count == 0)
1832     {
1833         ret = TRUE;
1834         goto done;
1835     }
1836
1837     pt.x = x;
1838     pt.y = y;
1839     LPtoDP(hdc, &pt, 1);
1840     x = pt.x;
1841     y = pt.y;
1842
1843     char_extra = GetTextCharacterExtra(hdc);
1844     width = 0;
1845     if(char_extra || dc->breakExtra || lpDx)
1846     {
1847         UINT i;
1848         SIZE tmpsz;
1849         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1850         for(i = 0; i < count; i++)
1851         {
1852             if(lpDx && (flags & ETO_PDY))
1853                 deltas[i] = lpDx[i*2] + char_extra;
1854             else if(lpDx)
1855                 deltas[i] = lpDx[i] + char_extra;
1856             else
1857             {
1858                 if(flags & ETO_GLYPH_INDEX)
1859                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1860                 else
1861                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1862
1863                 deltas[i] = tmpsz.cx;
1864             }
1865             
1866             if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1867             {
1868                 deltas[i] = deltas[i] + dc->breakExtra;
1869             }
1870             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1871             width += deltas[i];
1872         }
1873     }
1874     else
1875     {
1876         if(!done_extents)
1877         {
1878             if(flags & ETO_GLYPH_INDEX)
1879                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1880             else
1881                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1882             done_extents = TRUE;
1883         }
1884         width = INTERNAL_XWSTODS(dc, sz.cx);
1885     }
1886     xwidth = width * cosEsc;
1887     ywidth = width * sinEsc;
1888
1889     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1890     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1891     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1892     {
1893     case TA_LEFT:
1894         if (align & TA_UPDATECP)
1895         {
1896             pt.x = x + xwidth;
1897             pt.y = y - ywidth;
1898             DPtoLP(hdc, &pt, 1);
1899             MoveToEx(hdc, pt.x, pt.y, NULL);
1900         }
1901         break;
1902
1903     case TA_CENTER:
1904         x -= xwidth / 2;
1905         y += ywidth / 2;
1906         break;
1907
1908     case TA_RIGHT:
1909         x -= xwidth;
1910         y += ywidth;
1911         if (align & TA_UPDATECP)
1912         {
1913             pt.x = x;
1914             pt.y = y;
1915             DPtoLP(hdc, &pt, 1);
1916             MoveToEx(hdc, pt.x, pt.y, NULL);
1917         }
1918         break;
1919     }
1920
1921     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1922     {
1923     case TA_TOP:
1924         y += tm.tmAscent * cosEsc;
1925         x += tm.tmAscent * sinEsc;
1926         break;
1927
1928     case TA_BOTTOM:
1929         y -= tm.tmDescent * cosEsc;
1930         x -= tm.tmDescent * sinEsc;
1931         break;
1932
1933     case TA_BASELINE:
1934         break;
1935     }
1936
1937     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1938     {
1939         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1940         {
1941             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1942                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1943             {
1944                 RECT rc;
1945                 rc.left = x;
1946                 rc.right = x + width;
1947                 rc.top = y - tm.tmAscent;
1948                 rc.bottom = y + tm.tmDescent;
1949                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1950             }
1951         }
1952     }
1953
1954     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1955     {
1956         HFONT orig_font = dc->hFont, cur_font;
1957         UINT glyph;
1958         INT span = 0, *offsets = NULL, i;
1959
1960         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1961         for(i = 0; i < count; i++)
1962         {
1963             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1964             if(cur_font != dc->hFont)
1965             {
1966                 if(!offsets)
1967                 {
1968                     int j;
1969                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1970                     offsets[0] = 0;
1971                     if(!deltas)
1972                     {
1973                         SIZE tmpsz;
1974                         for(j = 1; j < count; j++)
1975                         {
1976                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1977                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1978                         }
1979                     }
1980                     else
1981                     {
1982                         for(j = 1; j < count; j++)
1983                             offsets[j] = offsets[j-1] + deltas[j];
1984                     }
1985                 }
1986                 if(span)
1987                 {
1988                     if (PATH_IsPathOpen(dc->path))
1989                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1990                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1991                                               glyphs, span, deltas ? deltas + i - span : NULL);
1992                     else
1993                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1994                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1995                                            glyphs, span, deltas ? deltas + i - span : NULL);
1996                     span = 0;
1997                 }
1998                 SelectObject(hdc, cur_font);
1999             }
2000             glyphs[span++] = glyph;
2001
2002             if(i == count - 1)
2003             {
2004                 if (PATH_IsPathOpen(dc->path))
2005                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2006                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
2007                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2008                                           glyphs, span, deltas ? deltas + count - span : NULL);
2009                 else
2010                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2011                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
2012                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2013                                              glyphs, span, deltas ? deltas + count - span : NULL);
2014                 SelectObject(hdc, orig_font);
2015                 HeapFree(GetProcessHeap(), 0, offsets);
2016            }
2017         }
2018     }
2019     else
2020     {
2021         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2022         {
2023             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2024             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2025             flags |= ETO_GLYPH_INDEX;
2026         }
2027
2028         if (PATH_IsPathOpen(dc->path))
2029             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2030                                   glyphs ? glyphs : reordered_str, count, deltas);
2031         else
2032             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2033                                      glyphs ? glyphs : reordered_str, count, deltas);
2034     }
2035
2036 done:
2037     HeapFree(GetProcessHeap(), 0, deltas);
2038     if(glyphs != reordered_str)
2039         HeapFree(GetProcessHeap(), 0, glyphs);
2040     if(reordered_str != str)
2041         HeapFree(GetProcessHeap(), 0, reordered_str);
2042
2043     GDI_ReleaseObj( hdc );
2044
2045     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2046     {
2047         int underlinePos, strikeoutPos;
2048         int underlineWidth, strikeoutWidth;
2049         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2050         OUTLINETEXTMETRICW* otm = NULL;
2051
2052         if(!size)
2053         {
2054             underlinePos = 0;
2055             underlineWidth = tm.tmAscent / 20 + 1;
2056             strikeoutPos = tm.tmAscent / 2;
2057             strikeoutWidth = underlineWidth;
2058         }
2059         else
2060         {
2061             otm = HeapAlloc(GetProcessHeap(), 0, size);
2062             GetOutlineTextMetricsW(hdc, size, otm);
2063             underlinePos = otm->otmsUnderscorePosition;
2064             underlineWidth = otm->otmsUnderscoreSize;
2065             strikeoutPos = otm->otmsStrikeoutPosition;
2066             strikeoutWidth = otm->otmsStrikeoutSize;
2067             HeapFree(GetProcessHeap(), 0, otm);
2068         }
2069
2070         if (PATH_IsPathOpen(dc->path))
2071         {
2072             POINT pts[5];
2073             HPEN hpen;
2074             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2075
2076             hbrush = SelectObject(hdc, hbrush);
2077             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2078
2079             if (lf.lfUnderline)
2080             {
2081                 pts[0].x = x - underlinePos * sinEsc;
2082                 pts[0].y = y - underlinePos * cosEsc;
2083                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2084                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2085                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2086                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2087                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2088                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2089                 pts[4].x = pts[0].x;
2090                 pts[4].y = pts[0].y;
2091                 DPtoLP(hdc, pts, 5);
2092                 Polygon(hdc, pts, 5);
2093             }
2094
2095             if (lf.lfStrikeOut)
2096             {
2097                 pts[0].x = x - strikeoutPos * sinEsc;
2098                 pts[0].y = y - strikeoutPos * cosEsc;
2099                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2100                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2101                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2102                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2103                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2104                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2105                 pts[4].x = pts[0].x;
2106                 pts[4].y = pts[0].y;
2107                 DPtoLP(hdc, pts, 5);
2108                 Polygon(hdc, pts, 5);
2109             }
2110
2111             SelectObject(hdc, hpen);
2112             hbrush = SelectObject(hdc, hbrush);
2113             DeleteObject(hbrush);
2114         }
2115         else
2116         {
2117             POINT pts[2], oldpt;
2118             HPEN hpen;
2119
2120             if (lf.lfUnderline)
2121             {
2122                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2123                 hpen = SelectObject(hdc, hpen);
2124                 pts[0].x = x;
2125                 pts[0].y = y;
2126                 pts[1].x = x + xwidth;
2127                 pts[1].y = y - ywidth;
2128                 DPtoLP(hdc, pts, 2);
2129                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2130                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2131                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2132                 DeleteObject(SelectObject(hdc, hpen));
2133             }
2134
2135             if (lf.lfStrikeOut)
2136             {
2137                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2138                 hpen = SelectObject(hdc, hpen);
2139                 pts[0].x = x;
2140                 pts[0].y = y;
2141                 pts[1].x = x + xwidth;
2142                 pts[1].y = y - ywidth;
2143                 DPtoLP(hdc, pts, 2);
2144                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2145                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2146                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2147                 DeleteObject(SelectObject(hdc, hpen));
2148             }
2149         }
2150     }
2151
2152     return ret;
2153 }
2154
2155
2156 /***********************************************************************
2157  *           TextOutA    (GDI32.@)
2158  */
2159 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2160 {
2161     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2162 }
2163
2164
2165 /***********************************************************************
2166  *           TextOutW    (GDI32.@)
2167  */
2168 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2169 {
2170     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2171 }
2172
2173
2174 /***********************************************************************
2175  *              PolyTextOutA (GDI32.@)
2176  *
2177  * See PolyTextOutW.
2178  */
2179 BOOL WINAPI PolyTextOutA ( HDC hdc,               /* [in] Handle to device context */
2180                            PPOLYTEXTA pptxt,      /* [in] Array of strings */
2181                            INT cStrings )         /* [in] Number of strings in array */
2182 {
2183     for (; cStrings>0; cStrings--, pptxt++)
2184         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2185             return FALSE;
2186     return TRUE;
2187 }
2188
2189
2190
2191 /***********************************************************************
2192  *              PolyTextOutW (GDI32.@)
2193  *
2194  * Draw several Strings
2195  *
2196  * RETURNS
2197  *  TRUE:  Success.
2198  *  FALSE: Failure.
2199  */
2200 BOOL WINAPI PolyTextOutW ( HDC hdc,               /* [in] Handle to device context */
2201                            PPOLYTEXTW pptxt,      /* [in] Array of strings */
2202                            INT cStrings )         /* [in] Number of strings in array */
2203 {
2204     for (; cStrings>0; cStrings--, pptxt++)
2205         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2206             return FALSE;
2207     return TRUE;
2208 }
2209
2210
2211 /* FIXME: all following APIs ******************************************/
2212
2213
2214 /***********************************************************************
2215  *           SetMapperFlags    (GDI32.@)
2216  */
2217 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2218 {
2219     DC *dc = DC_GetDCPtr( hDC );
2220     DWORD ret = 0;
2221     if(!dc) return 0;
2222     if(dc->funcs->pSetMapperFlags)
2223     {
2224         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2225         /* FIXME: ret is just a success flag, we should return a proper value */
2226     }
2227     else
2228         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2229     GDI_ReleaseObj( hDC );
2230     return ret;
2231 }
2232
2233 /***********************************************************************
2234  *          GetAspectRatioFilterEx  (GDI.486)
2235  */
2236 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2237 {
2238   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2239   return FALSE;
2240 }
2241
2242 /***********************************************************************
2243  *          GetAspectRatioFilterEx  (GDI32.@)
2244  */
2245 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2246 {
2247   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2248   return FALSE;
2249 }
2250
2251
2252 /***********************************************************************
2253  *           GetCharABCWidthsA   (GDI32.@)
2254  *
2255  * See GetCharABCWidthsW.
2256  */
2257 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2258                                   LPABC abc )
2259 {
2260     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2261     LPSTR str;
2262     LPWSTR wstr;
2263     BOOL ret = TRUE;
2264
2265     if(count <= 0) return FALSE;
2266
2267     str = HeapAlloc(GetProcessHeap(), 0, count);
2268     for(i = 0; i < count; i++)
2269         str[i] = (BYTE)(firstChar + i);
2270
2271     wstr = FONT_mbtowc(str, count, &wlen);
2272
2273     for(i = 0; i < wlen; i++)
2274     {
2275         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2276         {
2277             ret = FALSE;
2278             break;
2279         }
2280         abc++;
2281     }
2282
2283     HeapFree(GetProcessHeap(), 0, str);
2284     HeapFree(GetProcessHeap(), 0, wstr);
2285
2286     return ret;
2287 }
2288
2289
2290 /******************************************************************************
2291  * GetCharABCWidthsW [GDI32.@]
2292  *
2293  * Retrieves widths of characters in range.
2294  *
2295  * PARAMS
2296  *    hdc       [I] Handle of device context
2297  *    firstChar [I] First character in range to query
2298  *    lastChar  [I] Last character in range to query
2299  *    abc       [O] Address of character-width structure
2300  *
2301  * NOTES
2302  *    Only works with TrueType fonts
2303  *
2304  * RETURNS
2305  *    Success: TRUE
2306  *    Failure: FALSE
2307  */
2308 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2309                                    LPABC abc )
2310 {
2311     DC *dc = DC_GetDCPtr(hdc);
2312     unsigned int i;
2313     BOOL ret = FALSE;
2314
2315     if (!dc) return FALSE;
2316
2317     if(dc->gdiFont)
2318         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2319     else
2320         FIXME(": stub\n");
2321
2322     if (ret)
2323     {
2324         /* convert device units to logical */
2325         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2326             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2327             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2328             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2329         }
2330         ret = TRUE;
2331     }
2332
2333     GDI_ReleaseObj(hdc);
2334     return ret;
2335 }
2336
2337
2338 /******************************************************************************
2339  * GetCharABCWidthsI [GDI32.@]
2340  *
2341  * Retrieves widths of characters in range.
2342  *
2343  * PARAMS
2344  *    hdc       [I] Handle of device context
2345  *    firstChar [I] First glyphs in range to query
2346  *    count     [I] Last glyphs in range to query
2347  *    pgi       [i] Array of glyphs to query
2348  *    abc       [O] Address of character-width structure
2349  *
2350  * NOTES
2351  *    Only works with TrueType fonts
2352  *
2353  * RETURNS
2354  *    Success: TRUE
2355  *    Failure: FALSE
2356  */
2357 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2358                                LPWORD pgi, LPABC abc)
2359 {
2360     DC *dc = DC_GetDCPtr(hdc);
2361     unsigned int i;
2362     BOOL ret = FALSE;
2363
2364     if (!dc) return FALSE;
2365
2366     if(dc->gdiFont)
2367         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2368     else
2369         FIXME(": stub\n");
2370
2371     if (ret)
2372     {
2373         /* convert device units to logical */
2374         for( i = firstChar; i <= count; i++, abc++ ) {
2375             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2376             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2377             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2378         }
2379         ret = TRUE;
2380     }
2381
2382     GDI_ReleaseObj(hdc);
2383     return ret;
2384 }
2385
2386
2387 /***********************************************************************
2388  *           GetGlyphOutlineA    (GDI32.@)
2389  */
2390 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2391                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2392                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2393 {
2394     LPWSTR p = NULL;
2395     DWORD ret;
2396     UINT c;
2397
2398     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2399         int len;
2400         char mbchs[2];
2401         if(uChar > 0xff) { /* but, 2 bytes character only */
2402             len = 2;
2403             mbchs[0] = (uChar & 0xff00) >> 8;
2404             mbchs[1] = (uChar & 0xff);
2405         } else {
2406             len = 1;
2407             mbchs[0] = (uChar & 0xff);
2408         }
2409         p = FONT_mbtowc(mbchs, len, NULL);
2410         c = p[0];
2411     } else
2412         c = uChar;
2413     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2414                            lpmat2);
2415     HeapFree(GetProcessHeap(), 0, p);
2416     return ret;
2417 }
2418
2419 /***********************************************************************
2420  *           GetGlyphOutlineW    (GDI32.@)
2421  */
2422 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2423                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2424                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2425 {
2426     DC *dc = DC_GetDCPtr(hdc);
2427     DWORD ret;
2428
2429     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2430           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2431
2432     if(!dc) return GDI_ERROR;
2433
2434     if(dc->gdiFont)
2435       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2436                                    cbBuffer, lpBuffer, lpmat2);
2437     else
2438       ret = GDI_ERROR;
2439
2440     GDI_ReleaseObj(hdc);
2441     return ret;
2442 }
2443
2444
2445 /***********************************************************************
2446  *           CreateScalableFontResourceA   (GDI32.@)
2447  */
2448 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2449                                              LPCSTR lpszResourceFile,
2450                                              LPCSTR lpszFontFile,
2451                                              LPCSTR lpszCurrentPath )
2452 {
2453     HANDLE f;
2454
2455     /* fHidden=1 - only visible for the calling app, read-only, not
2456      * enumbered with EnumFonts/EnumFontFamilies
2457      * lpszCurrentPath can be NULL
2458      */
2459     FIXME("(%ld,%s,%s,%s): stub\n",
2460           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2461           debugstr_a(lpszCurrentPath) );
2462
2463     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2464     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2465         CloseHandle(f);
2466         SetLastError(ERROR_FILE_EXISTS);
2467         return FALSE;
2468     }
2469     return FALSE; /* create failed */
2470 }
2471
2472 /***********************************************************************
2473  *           CreateScalableFontResourceW   (GDI32.@)
2474  */
2475 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2476                                              LPCWSTR lpszResourceFile,
2477                                              LPCWSTR lpszFontFile,
2478                                              LPCWSTR lpszCurrentPath )
2479 {
2480     FIXME("(%ld,%p,%p,%p): stub\n",
2481           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2482     return FALSE; /* create failed */
2483 }
2484
2485 /*************************************************************************
2486  *             GetKerningPairsA   (GDI32.@)
2487  */
2488 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2489                                LPKERNINGPAIR lpKerningPairs )
2490 {
2491     return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2492 }
2493
2494
2495 /*************************************************************************
2496  *             GetKerningPairsW   (GDI32.@)
2497  */
2498 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2499                                  LPKERNINGPAIR lpKerningPairs )
2500 {
2501     unsigned int i;
2502     FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2503
2504     if(!lpKerningPairs) /* return the number of kerning pairs */
2505         return 0;
2506
2507     for (i = 0; i < cPairs; i++)
2508         lpKerningPairs[i].iKernAmount = 0;
2509     return 0;
2510 }
2511
2512 /*************************************************************************
2513  * TranslateCharsetInfo [GDI32.@]
2514  *
2515  * Fills a CHARSETINFO structure for a character set, code page, or
2516  * font. This allows making the correspondance between different labelings
2517  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2518  * of the same encoding.
2519  *
2520  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2521  * only one codepage should be set in *lpSrc.
2522  *
2523  * RETURNS
2524  *   TRUE on success, FALSE on failure.
2525  *
2526  */
2527 BOOL WINAPI TranslateCharsetInfo(
2528   LPDWORD lpSrc, /* [in]
2529        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2530        if flags == TCI_SRCCHARSET: a character set value
2531        if flags == TCI_SRCCODEPAGE: a code page value
2532                  */
2533   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2534   DWORD flags /* [in] determines interpretation of lpSrc */)
2535 {
2536     int index = 0;
2537     switch (flags) {
2538     case TCI_SRCFONTSIG:
2539         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2540       break;
2541     case TCI_SRCCODEPAGE:
2542       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2543       break;
2544     case TCI_SRCCHARSET:
2545       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2546       break;
2547     default:
2548       return FALSE;
2549     }
2550     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2551     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2552     return TRUE;
2553 }
2554
2555 /*************************************************************************
2556  *             GetFontLanguageInfo   (GDI32.@)
2557  */
2558 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2559 {
2560         FONTSIGNATURE fontsig;
2561         static const DWORD GCP_DBCS_MASK=0x003F0000,
2562                 GCP_DIACRITIC_MASK=0x00000000,
2563                 FLI_GLYPHS_MASK=0x00000000,
2564                 GCP_GLYPHSHAPE_MASK=0x00000040,
2565                 GCP_KASHIDA_MASK=0x00000000,
2566                 GCP_LIGATE_MASK=0x00000000,
2567                 GCP_USEKERNING_MASK=0x00000000,
2568                 GCP_REORDER_MASK=0x00000060;
2569
2570         DWORD result=0;
2571
2572         GetTextCharsetInfo( hdc, &fontsig, 0 );
2573         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2574
2575         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2576                 result|=GCP_DBCS;
2577
2578         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2579                 result|=GCP_DIACRITIC;
2580
2581         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2582                 result|=FLI_GLYPHS;
2583
2584         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2585                 result|=GCP_GLYPHSHAPE;
2586
2587         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2588                 result|=GCP_KASHIDA;
2589
2590         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2591                 result|=GCP_LIGATE;
2592
2593         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2594                 result|=GCP_USEKERNING;
2595
2596         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2597         if( GetTextAlign( hdc) & TA_RTLREADING )
2598             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2599                     result|=GCP_REORDER;
2600
2601         return result;
2602 }
2603
2604
2605 /*************************************************************************
2606  * GetFontData [GDI32.@]
2607  *
2608  * Retrieve data for TrueType font.
2609  *
2610  * RETURNS
2611  *
2612  * success: Number of bytes returned
2613  * failure: GDI_ERROR
2614  *
2615  * NOTES
2616  *
2617  * Calls SetLastError()
2618  *
2619  */
2620 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2621     LPVOID buffer, DWORD length)
2622 {
2623     DC *dc = DC_GetDCPtr(hdc);
2624     DWORD ret = GDI_ERROR;
2625
2626     if(!dc) return GDI_ERROR;
2627
2628     if(dc->gdiFont)
2629       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2630
2631     GDI_ReleaseObj(hdc);
2632     return ret;
2633 }
2634
2635 /*************************************************************************
2636  * GetGlyphIndicesA [GDI32.@]
2637  */
2638 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2639                               LPWORD pgi, DWORD flags)
2640 {
2641     DWORD ret;
2642     WCHAR *lpstrW;
2643     INT countW;
2644
2645     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2646           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2647
2648     lpstrW = FONT_mbtowc(lpstr, count, &countW);
2649     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2650     HeapFree(GetProcessHeap(), 0, lpstrW);
2651
2652     return ret;
2653 }
2654
2655 /*************************************************************************
2656  * GetGlyphIndicesW [GDI32.@]
2657  */
2658 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2659                               LPWORD pgi, DWORD flags)
2660 {
2661     DC *dc = DC_GetDCPtr(hdc);
2662     DWORD ret = GDI_ERROR;
2663
2664     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2665           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2666
2667     if(!dc) return GDI_ERROR;
2668
2669     if(dc->gdiFont)
2670         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2671
2672     GDI_ReleaseObj(hdc);
2673     return ret;
2674 }
2675
2676 /*************************************************************************
2677  * GetCharacterPlacementA [GDI32.@]
2678  *
2679  * See GetCharacterPlacementW.
2680  *
2681  * NOTES:
2682  *  the web browser control of ie4 calls this with dwFlags=0
2683  */
2684 DWORD WINAPI
2685 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2686                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2687                          DWORD dwFlags)
2688 {
2689     WCHAR *lpStringW;
2690     INT uCountW;
2691     GCP_RESULTSW resultsW;
2692     DWORD ret;
2693
2694     TRACE("%s, %d, %d, 0x%08lx\n",
2695           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2696
2697     /* both structs are equal in size */
2698     memcpy(&resultsW, lpResults, sizeof(resultsW));
2699
2700     lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2701     if(lpResults->lpOutString)
2702         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2703
2704     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2705
2706     lpResults->nGlyphs = resultsW.nGlyphs;
2707     lpResults->nMaxFit = resultsW.nMaxFit;
2708
2709     if(lpResults->lpOutString) {
2710         WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2711                             lpResults->lpOutString, uCount, NULL, NULL );
2712     }
2713
2714     HeapFree(GetProcessHeap(), 0, lpStringW);
2715     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2716
2717     return ret;
2718 }
2719
2720 /*************************************************************************
2721  * GetCharacterPlacementW [GDI32.@]
2722  *
2723  *   Retrieve information about a string. This includes the width, reordering,
2724  *   Glyphing and so on.
2725  *
2726  * RETURNS
2727  *
2728  *   The width and height of the string if successful, 0 if failed.
2729  *
2730  * BUGS
2731  *
2732  *   All flags except GCP_REORDER are not yet implemented.
2733  *   Reordering is not 100% complient to the Windows BiDi method.
2734  *   Caret positioning is not yet implemented for BiDi.
2735  *   Classes are not yet implemented.
2736  *
2737  */
2738 DWORD WINAPI
2739 GetCharacterPlacementW(
2740                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2741                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2742                 INT uCount,             /* [in] Number of WORDS in string. */
2743                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2744                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2745                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2746                 )
2747 {
2748     DWORD ret=0;
2749     SIZE size;
2750     UINT i, nSet;
2751
2752     TRACE("%s, %d, %d, 0x%08lx\n",
2753           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2754
2755     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2756           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2757             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2758             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2759             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2760
2761     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
2762     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2763     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2764         FIXME("Caret positions for complex scripts not implemented\n");
2765
2766         nSet = (UINT)uCount;
2767         if(nSet > lpResults->nGlyphs)
2768                 nSet = lpResults->nGlyphs;
2769
2770         /* return number of initialized fields */
2771         lpResults->nGlyphs = nSet;
2772
2773         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2774         {
2775                 /* Treat the case where no special handling was requested in a fastpath way */
2776                 /* copy will do if the GCP_REORDER flag is not set */
2777                 if(lpResults->lpOutString)
2778                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2779
2780                 if(lpResults->lpOrder)
2781                 {
2782                         for(i = 0; i < nSet; i++)
2783                                 lpResults->lpOrder[i] = i;
2784                 }
2785         } else
2786         {
2787             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2788                           nSet, lpResults->lpOrder );
2789         }
2790
2791         /* FIXME: Will use the placement chars */
2792         if (lpResults->lpDx)
2793         {
2794                 int c;
2795                 for (i = 0; i < nSet; i++)
2796                 {
2797                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2798                                 lpResults->lpDx[i]= c;
2799                 }
2800         }
2801
2802     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2803     {
2804         int pos = 0;
2805        
2806         lpResults->lpCaretPos[0] = 0;
2807         for (i = 1; i < nSet; i++)
2808             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2809                 lpResults->lpCaretPos[i] = (pos += size.cx);
2810     }
2811    
2812     if(lpResults->lpGlyphs)
2813         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2814
2815     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2816       ret = MAKELONG(size.cx, size.cy);
2817
2818     return ret;
2819 }
2820
2821 /*************************************************************************
2822  *      GetCharABCWidthsFloatA [GDI32.@]
2823  *
2824  * See GetCharABCWidthsFloatW.
2825  */
2826 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2827 {
2828     INT i, wlen, count = (INT)(last - first + 1);
2829     LPSTR str;
2830     LPWSTR wstr;
2831     BOOL ret = TRUE;
2832
2833     if (count <= 0) return FALSE;
2834
2835     str = HeapAlloc(GetProcessHeap(), 0, count);
2836
2837     for(i = 0; i < count; i++)
2838         str[i] = (BYTE)(first + i);
2839
2840     wstr = FONT_mbtowc(str, count, &wlen);
2841
2842     for (i = 0; i < wlen; i++)
2843     {
2844         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2845         {
2846             ret = FALSE;
2847             break;
2848         }
2849         abcf++;
2850     }
2851
2852     HeapFree( GetProcessHeap(), 0, str );
2853     HeapFree( GetProcessHeap(), 0, wstr );
2854
2855     return ret;
2856 }
2857
2858 /*************************************************************************
2859  *      GetCharABCWidthsFloatW [GDI32.@]
2860  *
2861  * Retrieves widths of a range of characters.
2862  *
2863  * PARAMS
2864  *    hdc   [I] Handle to device context.
2865  *    first [I] First character in range to query.
2866  *    last  [I] Last character in range to query.
2867  *    abcf  [O] Array of LPABCFLOAT structures.
2868  *
2869  * RETURNS
2870  *    Success: TRUE
2871  *    Failure: FALSE
2872  *
2873  * BUGS
2874  *    Only works with TrueType fonts. It also doesn't return real
2875  *    floats but converted integers because it's implemented on
2876  *    top of GetCharABCWidthsW.
2877  */
2878 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2879 {
2880     ABC *abc;
2881     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2882     BOOL ret;
2883
2884     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2885
2886     abc = HeapAlloc( GetProcessHeap(), 0, size );
2887     if (!abc) return FALSE;
2888
2889     ret = GetCharABCWidthsW( hdc, first, last, abc );
2890     if (ret)
2891     {
2892         for (i = first; i <= last; i++, abc++, abcf++)
2893         {
2894             abcf->abcfA = abc->abcA;
2895             abcf->abcfB = abc->abcB;
2896             abcf->abcfC = abc->abcC;
2897         }
2898     }
2899     HeapFree( GetProcessHeap(), 0, abc );
2900     return ret;
2901 }
2902
2903 /*************************************************************************
2904  *      GetCharWidthFloatA [GDI32.@]
2905  */
2906 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2907                                     UINT iLastChar, PFLOAT pxBuffer)
2908 {
2909        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2910        return 0;
2911 }
2912
2913 /*************************************************************************
2914  *      GetCharWidthFloatW [GDI32.@]
2915  */
2916 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2917                                     UINT iLastChar, PFLOAT pxBuffer)
2918 {
2919        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2920        return 0;
2921 }
2922
2923
2924 /***********************************************************************
2925  *                                                                     *
2926  *           Font Resource API                                         *
2927  *                                                                     *
2928  ***********************************************************************/
2929
2930 /***********************************************************************
2931  *           AddFontResourceA    (GDI32.@)
2932  */
2933 INT WINAPI AddFontResourceA( LPCSTR str )
2934 {
2935     return AddFontResourceExA( str, 0, NULL);
2936 }
2937
2938 /***********************************************************************
2939  *           AddFontResourceW    (GDI32.@)
2940  */
2941 INT WINAPI AddFontResourceW( LPCWSTR str )
2942 {
2943     return AddFontResourceExW(str, 0, NULL);
2944 }
2945
2946
2947 /***********************************************************************
2948  *           AddFontResourceExA    (GDI32.@)
2949  */
2950 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2951 {
2952     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2953     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2954     INT ret;
2955
2956     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2957     ret = AddFontResourceExW(strW, fl, pdv);
2958     HeapFree(GetProcessHeap(), 0, strW);
2959     return ret;
2960 }
2961
2962 /***********************************************************************
2963  *           AddFontResourceExW    (GDI32.@)
2964  */
2965 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2966 {
2967     return WineEngAddFontResourceEx(str, fl, pdv);
2968 }
2969
2970 /***********************************************************************
2971  *           RemoveFontResourceA    (GDI32.@)
2972  */
2973 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2974 {
2975     return RemoveFontResourceExA(str, 0, 0);
2976 }
2977
2978 /***********************************************************************
2979  *           RemoveFontResourceW    (GDI32.@)
2980  */
2981 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2982 {
2983     return RemoveFontResourceExW(str, 0, 0);
2984 }
2985
2986 /***********************************************************************
2987  *           AddFontMemResourceEx    (GDI32.@)
2988  */
2989 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2990 {
2991     FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
2992     return NULL;
2993 }
2994
2995 /***********************************************************************
2996  *           RemoveFontResourceExA    (GDI32.@)
2997  */
2998 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2999 {
3000     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3001     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3002     INT ret;
3003
3004     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3005     ret = RemoveFontResourceExW(strW, fl, pdv);
3006     HeapFree(GetProcessHeap(), 0, strW);
3007     return ret;
3008 }
3009
3010 /***********************************************************************
3011  *           RemoveFontResourceExW    (GDI32.@)
3012  */
3013 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3014 {
3015     return WineEngRemoveFontResourceEx(str, fl, pdv);
3016 }
3017
3018 /***********************************************************************
3019  *           GetTextCharset    (GDI32.@)
3020  */
3021 UINT WINAPI GetTextCharset(HDC hdc)
3022 {
3023     /* MSDN docs say this is equivalent */
3024     return GetTextCharsetInfo(hdc, NULL, 0);
3025 }
3026
3027 /***********************************************************************
3028  *           GetTextCharsetInfo    (GDI32.@)
3029  */
3030 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3031 {
3032     UINT ret = DEFAULT_CHARSET;
3033     DC *dc = DC_GetDCPtr(hdc);
3034
3035     if (!dc) goto done;
3036
3037     if (dc->gdiFont)
3038         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3039
3040     GDI_ReleaseObj(hdc);
3041
3042 done:
3043     if (ret == DEFAULT_CHARSET && fs)
3044         memset(fs, 0, sizeof(FONTSIGNATURE));
3045     return ret;
3046 }
3047
3048 /***********************************************************************
3049  *           GdiGetCharDimensions    (GDI32.@)
3050  *
3051  * Gets the average width of the characters in the English alphabet.
3052  *
3053  * PARAMS
3054  *  hdc    [I] Handle to the device context to measure on.
3055  *  lptm   [O] Pointer to memory to store the text metrics into.
3056  *  height [O] On exit, the maximum height of characters in the English alphabet.
3057  *
3058  * RETURNS
3059  *  The average width of characters in the English alphabet.
3060  *
3061  * NOTES
3062  *  This function is used by the dialog manager to get the size of a dialog
3063  *  unit. It should also be used by other pieces of code that need to know
3064  *  the size of a dialog unit in logical units without having access to the
3065  *  window handle of the dialog.
3066  *  Windows caches the font metrics from this function, but we don't and
3067  *  there doesn't appear to be an immediate advantage to do so.
3068  *
3069  * SEE ALSO
3070  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3071  */
3072 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3073 {
3074     SIZE sz;
3075     static const WCHAR alphabet[] = {
3076         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3077         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3078         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3079
3080     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3081
3082     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3083
3084     if (height) *height = sz.cy;
3085     return (sz.cx / 26 + 1) / 2;
3086 }
3087
3088 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3089 {
3090     FIXME("(%d): stub\n", fEnableEUDC);
3091     return FALSE;
3092 }
3093
3094 /***********************************************************************
3095  *           GetCharWidthI    (GDI32.@)
3096  */
3097 BOOL WINAPI GetCharWidthI(HDC hdc, UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer)
3098 {
3099     FIXME("(%p, %d, %d, %p, %p): stub\n", hdc, giFirst, cgi, pgi, lpBuffer);
3100     return FALSE;
3101 }
3102
3103 /***********************************************************************
3104  *           GetFontUnicodeRanges    (GDI32.@)
3105  */
3106 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3107 {
3108     FIXME("(%p, %p): stub\n", hdc, lpgs);
3109     return 0;
3110 }