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