oleaut32: Implement GetVarDesc_Proxy and friends.
[wine] / dlls / gdi / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
42
43   /* Device -> World size conversion */
44
45 /* Performs a device to world transformation on the specified width (which
46  * is in integer format).
47  */
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
49 {
50     FLOAT floatWidth;
51
52     /* Perform operation with floating point */
53     floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54     /* Round to integers */
55     return GDI_ROUND(floatWidth);
56 }
57
58 /* Performs a device to world transformation on the specified size (which
59  * is in integer format).
60  */
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
62 {
63     FLOAT floatHeight;
64
65     /* Perform operation with floating point */
66     floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67     /* Round to integers */
68     return GDI_ROUND(floatHeight);
69 }
70
71 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
72 {
73     POINT pt[2];
74     pt[0].x = pt[0].y = 0;
75     pt[1].x = width;
76     pt[1].y = 0;
77     LPtoDP(dc->hSelf, pt, 2);
78     return pt[1].x - pt[0].x;
79 }
80
81 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
82 {
83     POINT pt[2];
84     pt[0].x = pt[0].y = 0;
85     pt[1].x = 0;
86     pt[1].y = height;
87     LPtoDP(dc->hSelf, pt, 2);
88     return pt[1].y - pt[0].y;
89 }
90
91 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
92 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
94 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
95 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
96
97 static const struct gdi_obj_funcs font_funcs =
98 {
99     FONT_SelectObject,  /* pSelectObject */
100     FONT_GetObject16,   /* pGetObject16 */
101     FONT_GetObjectA,    /* pGetObjectA */
102     FONT_GetObjectW,    /* pGetObjectW */
103     NULL,               /* pUnrealizeObject */
104     FONT_DeleteObject   /* pDeleteObject */
105 };
106
107 #define ENUM_UNICODE    0x00000001
108 #define ENUM_CALLED     0x00000002
109
110 typedef struct
111 {
112     GDIOBJHDR   header;
113     LOGFONTW    logfont;
114 } FONTOBJ;
115
116 typedef struct
117 {
118   LPLOGFONT16           lpLogFontParam;
119   FONTENUMPROC16        lpEnumFunc;
120   LPARAM                lpData;
121
122   LPNEWTEXTMETRICEX16   lpTextMetric;
123   LPENUMLOGFONTEX16     lpLogFont;
124   SEGPTR                segTextMetric;
125   SEGPTR                segLogFont;
126   DWORD                 dwFlags;
127   HDC                   hdc;
128   DC                   *dc;
129   PHYSDEV               physDev;
130 } fontEnum16;
131
132 typedef struct
133 {
134   LPLOGFONTW          lpLogFontParam;
135   FONTENUMPROCW       lpEnumFunc;
136   LPARAM              lpData;
137   DWORD               dwFlags;
138   HDC                 hdc;
139   DC                 *dc;
140   PHYSDEV             physDev;
141 } fontEnum32;
142
143 /*
144  *  For TranslateCharsetInfo
145  */
146 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
147 #define MAXTCIINDEX 32
148 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
149   /* ANSI */
150   { ANSI_CHARSET, 1252, FS(0)},
151   { EASTEUROPE_CHARSET, 1250, FS(1)},
152   { RUSSIAN_CHARSET, 1251, FS(2)},
153   { GREEK_CHARSET, 1253, FS(3)},
154   { TURKISH_CHARSET, 1254, FS(4)},
155   { HEBREW_CHARSET, 1255, FS(5)},
156   { ARABIC_CHARSET, 1256, FS(6)},
157   { BALTIC_CHARSET, 1257, FS(7)},
158   { VIETNAMESE_CHARSET, 1258, FS(8)},
159   /* reserved by ANSI */
160   { DEFAULT_CHARSET, 0, FS(0)},
161   { DEFAULT_CHARSET, 0, FS(0)},
162   { DEFAULT_CHARSET, 0, FS(0)},
163   { DEFAULT_CHARSET, 0, FS(0)},
164   { DEFAULT_CHARSET, 0, FS(0)},
165   { DEFAULT_CHARSET, 0, FS(0)},
166   { DEFAULT_CHARSET, 0, FS(0)},
167   /* ANSI and OEM */
168   { THAI_CHARSET,  874,  FS(16)},
169   { SHIFTJIS_CHARSET, 932, FS(17)},
170   { GB2312_CHARSET, 936, FS(18)},
171   { HANGEUL_CHARSET, 949, FS(19)},
172   { CHINESEBIG5_CHARSET, 950, FS(20)},
173   { JOHAB_CHARSET, 1361, FS(21)},
174   /* reserved for alternate ANSI and OEM */
175   { DEFAULT_CHARSET, 0, FS(0)},
176   { DEFAULT_CHARSET, 0, FS(0)},
177   { DEFAULT_CHARSET, 0, FS(0)},
178   { DEFAULT_CHARSET, 0, FS(0)},
179   { DEFAULT_CHARSET, 0, FS(0)},
180   { DEFAULT_CHARSET, 0, FS(0)},
181   { DEFAULT_CHARSET, 0, FS(0)},
182   { DEFAULT_CHARSET, 0, FS(0)},
183   /* reserved for system */
184   { DEFAULT_CHARSET, 0, FS(0)},
185   { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 };
187
188 /***********************************************************************
189  *              LOGFONT conversion functions.
190  */
191 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
192 {
193     font16->lfHeight = font32->lfHeight;
194     font16->lfWidth = font32->lfWidth;
195     font16->lfEscapement = font32->lfEscapement;
196     font16->lfOrientation = font32->lfOrientation;
197     font16->lfWeight = font32->lfWeight;
198     font16->lfItalic = font32->lfItalic;
199     font16->lfUnderline = font32->lfUnderline;
200     font16->lfStrikeOut = font32->lfStrikeOut;
201     font16->lfCharSet = font32->lfCharSet;
202     font16->lfOutPrecision = font32->lfOutPrecision;
203     font16->lfClipPrecision = font32->lfClipPrecision;
204     font16->lfQuality = font32->lfQuality;
205     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
206     WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
207                          font16->lfFaceName, LF_FACESIZE, NULL, NULL );
208     font16->lfFaceName[LF_FACESIZE-1] = 0;
209 }
210
211 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
212 {
213     font32->lfHeight = font16->lfHeight;
214     font32->lfWidth = font16->lfWidth;
215     font32->lfEscapement = font16->lfEscapement;
216     font32->lfOrientation = font16->lfOrientation;
217     font32->lfWeight = font16->lfWeight;
218     font32->lfItalic = font16->lfItalic;
219     font32->lfUnderline = font16->lfUnderline;
220     font32->lfStrikeOut = font16->lfStrikeOut;
221     font32->lfCharSet = font16->lfCharSet;
222     font32->lfOutPrecision = font16->lfOutPrecision;
223     font32->lfClipPrecision = font16->lfClipPrecision;
224     font32->lfQuality = font16->lfQuality;
225     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
226     MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
227     font32->lfFaceName[LF_FACESIZE-1] = 0;
228 }
229
230 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
231 {
232     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
233     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
234                         LF_FACESIZE);
235     fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 }
237
238 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
239 {
240     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
241     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
242                         LF_FACESIZE, NULL, NULL);
243     fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 }
245
246 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
247 {
248     FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
249
250     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
251                          (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
252     font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
253     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
254                          (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
255     font16->elfStyle[LF_FACESIZE-1] = '\0';
256     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
257                          (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
258     font16->elfScript[LF_FACESIZE-1] = '\0';
259 }
260
261 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
262 {
263     FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
264
265     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
266                          (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
267     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
268     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
269                          (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
270     fontA->elfStyle[LF_FACESIZE-1] = '\0';
271     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
272                          (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
273     fontA->elfScript[LF_FACESIZE-1] = '\0';
274 }
275
276 /***********************************************************************
277  *              TEXTMETRIC conversion functions.
278  */
279 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
280 {
281     ptmA->tmHeight = ptmW->tmHeight;
282     ptmA->tmAscent = ptmW->tmAscent;
283     ptmA->tmDescent = ptmW->tmDescent;
284     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
285     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
286     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
287     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
288     ptmA->tmWeight = ptmW->tmWeight;
289     ptmA->tmOverhang = ptmW->tmOverhang;
290     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
291     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
292     ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
293     ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
294     ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
295     ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
296     ptmA->tmItalic = ptmW->tmItalic;
297     ptmA->tmUnderlined = ptmW->tmUnderlined;
298     ptmA->tmStruckOut = ptmW->tmStruckOut;
299     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
300     ptmA->tmCharSet = ptmW->tmCharSet;
301 }
302
303
304 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
305 {
306     ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
307     ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
308     ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
309     ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
310     ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
311     ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
312     ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
313     ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
314     ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
315     ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
316     ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
317     ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
318     ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
319     ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
320     ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
321     ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
322     ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
323     ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
324     ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
325     ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
326     ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
327     ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
328     ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
329     ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
330     memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
331 }
332
333 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
334 {
335     FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
336     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
337     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
338     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
339     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
340     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
341 }
342
343
344 /***********************************************************************
345  *           FONT_mbtowc
346  *
347  * Returns a Unicode translation of str. 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     LPWSTR p = FONT_mbtowc(str, count, &wlen);
1148     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1149     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1150     HeapFree( GetProcessHeap(), 0, p );
1151     return ret;
1152 }
1153
1154
1155 /***********************************************************************
1156  *           GetTextExtentExPointW    (GDI32.@)
1157  *
1158  * Return the size of the string as it would be if it was output properly by
1159  * e.g. TextOut.
1160  *
1161  * This should include
1162  * - Intercharacter spacing
1163  * - justification spacing (not yet done)
1164  * - kerning? see below
1165  *
1166  * Kerning.  Since kerning would be carried out by the rendering code it should
1167  * be done by the driver.  However they don't support it yet.  Also I am not
1168  * yet persuaded that (certainly under Win95) any kerning is actually done.
1169  *
1170  * str: According to MSDN this should be null-terminated.  That is not true; a
1171  *      null will not terminate it early.
1172  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1173  *       than count.  I have seen it be either the size of the full string or
1174  *       1 less than the size of the full string.  I have not seen it bear any
1175  *       resemblance to the portion that would fit.
1176  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1177  *         trailing intercharacter spacing and any trailing justification.
1178  *
1179  * FIXME
1180  * Currently we do this by measuring each character etc.  We should do it by
1181  * passing the request to the driver, perhaps by extending the
1182  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1183  * thinking about kerning issues and rounding issues in the justification.
1184  */
1185
1186 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1187                                    INT maxExt, LPINT lpnFit,
1188                                    LPINT alpDx, LPSIZE size )
1189 {
1190     int index, nFit, extent;
1191     SIZE tSize;
1192     BOOL ret = FALSE;
1193
1194     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1195
1196     size->cx = size->cy = nFit = extent = 0;
1197     for(index = 0; index < count; index++)
1198     {
1199         if(!GetTextExtentPoint32W( hdc, str, index + 1, &tSize )) goto done;
1200         /* GetTextExtentPoint includes intercharacter spacing. */
1201         /* FIXME - justification needs doing yet.  Remember that the base
1202          * data will not be in logical coordinates.
1203          */
1204         extent = tSize.cx;
1205         if( !lpnFit || extent <= maxExt )
1206         /* It is allowed to be equal. */
1207         {
1208             nFit++;
1209             if( alpDx ) alpDx[index] = extent;
1210         }
1211         if( tSize.cy > size->cy ) size->cy = tSize.cy;
1212     }
1213     size->cx = extent;
1214     if(lpnFit) *lpnFit = nFit;
1215     ret = TRUE;
1216
1217     TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1218
1219 done:
1220     return ret;
1221 }
1222
1223 /***********************************************************************
1224  *           GetTextMetricsA    (GDI32.@)
1225  */
1226 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1227 {
1228     TEXTMETRICW tm32;
1229
1230     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1231     FONT_TextMetricWToA( &tm32, metrics );
1232     return TRUE;
1233 }
1234
1235 /***********************************************************************
1236  *           GetTextMetricsW    (GDI32.@)
1237  */
1238 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1239 {
1240     BOOL ret = FALSE;
1241     DC * dc = DC_GetDCPtr( hdc );
1242     if (!dc) return FALSE;
1243
1244     if (dc->gdiFont)
1245         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1246     else if (dc->funcs->pGetTextMetrics)
1247         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1248
1249     if (ret)
1250     {
1251     /* device layer returns values in device units
1252      * therefore we have to convert them to logical */
1253
1254 #define WDPTOLP(x) ((x<0)?                                      \
1255                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1256                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1257 #define HDPTOLP(y) ((y<0)?                                      \
1258                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1259                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1260
1261     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1262     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1263     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1264     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1265     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1266     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1267     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1268     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1269         ret = TRUE;
1270 #undef WDPTOLP
1271 #undef HDPTOLP
1272     TRACE("text metrics:\n"
1273           "    Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1274           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1275           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1276           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1277           "    PitchAndFamily = %02x\n"
1278           "    --------------------\n"
1279           "    InternalLeading = %li\n"
1280           "    Ascent = %li\n"
1281           "    Descent = %li\n"
1282           "    Height = %li\n",
1283           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1284           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1285           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1286           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1287           metrics->tmPitchAndFamily,
1288           metrics->tmInternalLeading,
1289           metrics->tmAscent,
1290           metrics->tmDescent,
1291           metrics->tmHeight );
1292     }
1293     GDI_ReleaseObj( hdc );
1294     return ret;
1295 }
1296
1297
1298 /***********************************************************************
1299  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1300  *
1301  * NOTES
1302  *    lpOTM should be LPOUTLINETEXTMETRIC
1303  *
1304  * RETURNS
1305  *    Success: Non-zero or size of required buffer
1306  *    Failure: 0
1307  */
1308 UINT16 WINAPI GetOutlineTextMetrics16(
1309     HDC16 hdc,    /* [in]  Handle of device context */
1310     UINT16 cbData, /* [in]  Size of metric data array */
1311     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1312 {
1313     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1314     return 0;
1315 }
1316
1317
1318 /***********************************************************************
1319  *              GetOutlineTextMetricsA (GDI32.@)
1320  * Gets metrics for TrueType fonts.
1321  *
1322  * NOTES
1323  *    If the supplied buffer isn't big enough Windows partially fills it up to
1324  *    its given length and returns that length.
1325  *
1326  * RETURNS
1327  *    Success: Non-zero or size of required buffer
1328  *    Failure: 0
1329  */
1330 UINT WINAPI GetOutlineTextMetricsA(
1331     HDC hdc,    /* [in]  Handle of device context */
1332     UINT cbData, /* [in]  Size of metric data array */
1333     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1334 {
1335     char buf[512], *ptr;
1336     UINT ret, needed;
1337     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1338     OUTLINETEXTMETRICA *output = lpOTM;
1339     INT left, len;
1340
1341     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1342         return 0;
1343     if(ret > sizeof(buf))
1344         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1345     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1346
1347     needed = sizeof(OUTLINETEXTMETRICA);
1348     if(lpOTMW->otmpFamilyName)
1349         needed += WideCharToMultiByte(CP_ACP, 0,
1350            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1351                                       NULL, 0, NULL, NULL);
1352     if(lpOTMW->otmpFaceName)
1353         needed += WideCharToMultiByte(CP_ACP, 0,
1354            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1355                                       NULL, 0, NULL, NULL);
1356     if(lpOTMW->otmpStyleName)
1357         needed += WideCharToMultiByte(CP_ACP, 0,
1358            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1359                                       NULL, 0, NULL, NULL);
1360     if(lpOTMW->otmpFullName)
1361         needed += WideCharToMultiByte(CP_ACP, 0,
1362            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1363                                       NULL, 0, NULL, NULL);
1364
1365     if(!lpOTM) {
1366         ret = needed;
1367         goto end;
1368     }
1369
1370     TRACE("needed = %d\n", needed);
1371     if(needed > cbData)
1372         /* Since the supplied buffer isn't big enough, we'll alloc one
1373            that is and memcpy the first cbData bytes into the lpOTM at
1374            the end. */
1375         output = HeapAlloc(GetProcessHeap(), 0, needed);
1376
1377     ret = output->otmSize = min(needed, cbData);
1378     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1379     output->otmFiller = 0;
1380     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1381     output->otmfsSelection = lpOTMW->otmfsSelection;
1382     output->otmfsType = lpOTMW->otmfsType;
1383     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1384     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1385     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1386     output->otmEMSquare = lpOTMW->otmEMSquare;
1387     output->otmAscent = lpOTMW->otmAscent;
1388     output->otmDescent = lpOTMW->otmDescent;
1389     output->otmLineGap = lpOTMW->otmLineGap;
1390     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1391     output->otmsXHeight = lpOTMW->otmsXHeight;
1392     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1393     output->otmMacAscent = lpOTMW->otmMacAscent;
1394     output->otmMacDescent = lpOTMW->otmMacDescent;
1395     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1396     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1397     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1398     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1399     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1400     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1401     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1402     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1403     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1404     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1405
1406
1407     ptr = (char*)(output + 1);
1408     left = needed - sizeof(*output);
1409
1410     if(lpOTMW->otmpFamilyName) {
1411         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1412         len = WideCharToMultiByte(CP_ACP, 0,
1413              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1414                                   ptr, left, NULL, NULL);
1415         left -= len;
1416         ptr += len;
1417     } else
1418         output->otmpFamilyName = 0;
1419
1420     if(lpOTMW->otmpFaceName) {
1421         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1422         len = WideCharToMultiByte(CP_ACP, 0,
1423              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1424                                   ptr, left, NULL, NULL);
1425         left -= len;
1426         ptr += len;
1427     } else
1428         output->otmpFaceName = 0;
1429
1430     if(lpOTMW->otmpStyleName) {
1431         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1432         len = WideCharToMultiByte(CP_ACP, 0,
1433              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1434                                   ptr, left, NULL, NULL);
1435         left -= len;
1436         ptr += len;
1437     } else
1438         output->otmpStyleName = 0;
1439
1440     if(lpOTMW->otmpFullName) {
1441         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1442         len = WideCharToMultiByte(CP_ACP, 0,
1443              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1444                                   ptr, left, NULL, NULL);
1445         left -= len;
1446     } else
1447         output->otmpFullName = 0;
1448
1449     assert(left == 0);
1450
1451     if(output != lpOTM) {
1452         memcpy(lpOTM, output, cbData);
1453         HeapFree(GetProcessHeap(), 0, output);
1454     }
1455
1456 end:
1457     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1458         HeapFree(GetProcessHeap(), 0, lpOTMW);
1459
1460     return ret;
1461 }
1462
1463
1464 /***********************************************************************
1465  *           GetOutlineTextMetricsW [GDI32.@]
1466  */
1467 UINT WINAPI GetOutlineTextMetricsW(
1468     HDC hdc,    /* [in]  Handle of device context */
1469     UINT cbData, /* [in]  Size of metric data array */
1470     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1471 {
1472     DC *dc = DC_GetDCPtr( hdc );
1473     OUTLINETEXTMETRICW *output = lpOTM;
1474     UINT ret;
1475
1476     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1477     if(!dc) return 0;
1478
1479     if(dc->gdiFont) {
1480         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1481         if(lpOTM && ret) {
1482             if(ret > cbData) {
1483                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1484                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1485             }
1486
1487 #define WDPTOLP(x) ((x<0)?                                      \
1488                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1489                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1490 #define HDPTOLP(y) ((y<0)?                                      \
1491                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1492                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1493
1494             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1495             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1496             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1497             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1498             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1499             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1500             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1501             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1502             output->otmAscent = HDPTOLP(output->otmAscent);
1503             output->otmDescent = HDPTOLP(output->otmDescent);
1504             output->otmLineGap = HDPTOLP(output->otmLineGap);
1505             output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1506             output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1507             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1508             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1509             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1510             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1511             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1512             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1513             output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1514             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1515             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1516             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1517             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1518             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1519             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1520             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1521             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1522             output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1523             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1524             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1525             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1526 #undef WDPTOLP
1527 #undef HDPTOLP
1528             if(output != lpOTM) {
1529                 memcpy(lpOTM, output, cbData);
1530                 HeapFree(GetProcessHeap(), 0, output);
1531                 ret = cbData;
1532             }
1533         }
1534     }
1535
1536     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1537               but really this should just be a return 0. */
1538
1539         ret = sizeof(*lpOTM);
1540         if (lpOTM) {
1541             if(cbData < ret)
1542                 ret = 0;
1543             else {
1544                 memset(lpOTM, 0, ret);
1545                 lpOTM->otmSize = sizeof(*lpOTM);
1546                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1547                 /*
1548                   Further fill of the structure not implemented,
1549                   Needs real values for the structure members
1550                 */
1551             }
1552         }
1553     }
1554     GDI_ReleaseObj(hdc);
1555     return ret;
1556 }
1557
1558
1559 /***********************************************************************
1560  *           GetCharWidthW      (GDI32.@)
1561  *           GetCharWidth32W    (GDI32.@)
1562  */
1563 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1564                                LPINT buffer )
1565 {
1566     UINT i;
1567     BOOL ret = FALSE;
1568     DC * dc = DC_GetDCPtr( hdc );
1569     if (!dc) return FALSE;
1570
1571     if (dc->gdiFont)
1572         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1573     else if (dc->funcs->pGetCharWidth)
1574         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1575
1576     if (ret)
1577     {
1578         /* convert device units to logical */
1579         for( i = firstChar; i <= lastChar; i++, buffer++ )
1580             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1581         ret = TRUE;
1582     }
1583     GDI_ReleaseObj( hdc );
1584     return ret;
1585 }
1586
1587
1588 /***********************************************************************
1589  *           GetCharWidthA      (GDI32.@)
1590  *           GetCharWidth32A    (GDI32.@)
1591  */
1592 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1593                                LPINT buffer )
1594 {
1595     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1596     LPSTR str;
1597     LPWSTR wstr;
1598     BOOL ret = TRUE;
1599
1600     if(count <= 0) return FALSE;
1601
1602     str = HeapAlloc(GetProcessHeap(), 0, count);
1603     for(i = 0; i < count; i++)
1604         str[i] = (BYTE)(firstChar + i);
1605
1606     wstr = FONT_mbtowc(str, count, &wlen);
1607
1608     for(i = 0; i < wlen; i++)
1609     {
1610         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1611         {
1612             ret = FALSE;
1613             break;
1614         }
1615         buffer++;
1616     }
1617
1618     HeapFree(GetProcessHeap(), 0, str);
1619     HeapFree(GetProcessHeap(), 0, wstr);
1620
1621     return ret;
1622 }
1623
1624
1625 /***********************************************************************
1626  *           ExtTextOutA    (GDI32.@)
1627  *
1628  * See ExtTextOutW.
1629  */
1630 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1631                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1632 {
1633     INT wlen;
1634     LPWSTR p;
1635     BOOL ret;
1636     LPINT lpDxW = NULL;
1637
1638     if (flags & ETO_GLYPH_INDEX)
1639         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1640
1641     p = FONT_mbtowc(str, count, &wlen);
1642
1643     if (lpDx) {
1644         unsigned int i = 0, j = 0;
1645
1646         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1647         while(i < count) {
1648             if(IsDBCSLeadByte(str[i])) {
1649                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1650                 i = i + 2;
1651             } else {
1652                 lpDxW[j++] = lpDx[i];
1653                 i = i + 1;
1654             }
1655         }
1656     }
1657
1658     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1659
1660     HeapFree( GetProcessHeap(), 0, p );
1661     HeapFree( GetProcessHeap(), 0, lpDxW );
1662     return ret;
1663 }
1664
1665
1666 /***********************************************************************
1667  *           ExtTextOutW    (GDI32.@)
1668  *
1669  * Draws text using the currently selected font, background color, and text color.
1670  * 
1671  * 
1672  * PARAMS
1673  *    x,y    [I] coordinates of string
1674  *    flags  [I]
1675  *        ETO_GRAYED - undocumented on MSDN
1676  *        ETO_OPAQUE - use background color for fill the rectangle
1677  *        ETO_CLIPPED - clipping text to the rectangle
1678  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1679  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1680  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1681  *                         Affects BiDi ordering
1682  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1683  *        ETO_PDY - unimplemented
1684  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1685  *                            do not translate numbers into locale representations
1686  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1687  *    lprect [I] dimensions for clipping or/and opaquing
1688  *    str    [I] text string
1689  *    count  [I] number of symbols in string
1690  *    lpDx   [I] optional parameter with distance between drawing characters
1691  *
1692  * RETURNS
1693  *    Success: TRUE
1694  *    Failure: FALSE
1695  */
1696 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1697                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1698 {
1699     BOOL ret = FALSE;
1700     LPWSTR reordered_str = (LPWSTR)str;
1701     WORD *glyphs = NULL;
1702     UINT align = GetTextAlign( hdc );
1703     POINT pt;
1704     TEXTMETRICW tm;
1705     LOGFONTW lf;
1706     double cosEsc, sinEsc;
1707     INT *deltas = NULL, char_extra;
1708     SIZE sz;
1709     RECT rc;
1710     BOOL done_extents = FALSE;
1711     INT width, xwidth = 0, ywidth = 0;
1712     DWORD type;
1713     DC * dc = DC_GetDCUpdate( hdc );
1714
1715     if (!dc) return FALSE;
1716
1717     if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1718         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1719
1720     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1721     {
1722         GDI_ReleaseObj( hdc );
1723         return ret;
1724     }
1725
1726     type = GetObjectType(hdc);
1727     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1728     {
1729         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1730         GDI_ReleaseObj( hdc );
1731         return ret;
1732     }
1733         
1734     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1735     {
1736         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1737
1738         BIDI_Reorder( str, count, GCP_REORDER,
1739                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1740                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1741                       reordered_str, count, NULL );
1742     
1743         flags |= ETO_IGNORELANGUAGE;
1744     }
1745
1746     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1747           lprect, debugstr_wn(str, count), count, lpDx);
1748
1749     if(flags & ETO_GLYPH_INDEX)
1750         glyphs = reordered_str;
1751
1752     if(lprect)
1753         TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1754               lprect->bottom);
1755     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1756
1757     if(align & TA_UPDATECP)
1758     {
1759         GetCurrentPositionEx( hdc, &pt );
1760         x = pt.x;
1761         y = pt.y;
1762     }
1763
1764     GetTextMetricsW(hdc, &tm);
1765     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1766
1767     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1768         lf.lfEscapement = 0;
1769
1770     if(lf.lfEscapement != 0)
1771     {
1772         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1773         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1774     }
1775     else
1776     {
1777         cosEsc = 1;
1778         sinEsc = 0;
1779     }
1780
1781     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1782     {
1783         if(!lprect)
1784         {
1785             if(flags & ETO_CLIPPED) goto done;
1786             if(flags & ETO_GLYPH_INDEX)
1787                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1788             else
1789                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1790
1791             done_extents = TRUE;
1792             rc.left = x;
1793             rc.top = y;
1794             rc.right = x + sz.cx;
1795             rc.bottom = y + sz.cy;
1796         }
1797         else
1798         {
1799             rc = *lprect;
1800         }
1801
1802         LPtoDP(hdc, (POINT*)&rc, 2);
1803
1804         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1805         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1806     }
1807
1808     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1809         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1810
1811     if(count == 0)
1812     {
1813         ret = TRUE;
1814         goto done;
1815     }
1816
1817     pt.x = x;
1818     pt.y = y;
1819     LPtoDP(hdc, &pt, 1);
1820     x = pt.x;
1821     y = pt.y;
1822
1823     char_extra = GetTextCharacterExtra(hdc);
1824     width = 0;
1825     if(char_extra || dc->breakExtra || lpDx)
1826     {
1827         UINT i;
1828         SIZE tmpsz;
1829         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1830         for(i = 0; i < count; i++)
1831         {
1832             if(lpDx)
1833                 deltas[i] = lpDx[i] + char_extra;
1834             else
1835             {
1836                 if(flags & ETO_GLYPH_INDEX)
1837                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1838                 else
1839                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1840
1841                 deltas[i] = tmpsz.cx;
1842             }
1843             
1844             if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1845             {
1846                 deltas[i] = deltas[i] + dc->breakExtra;
1847             }
1848             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1849             width += deltas[i];
1850         }
1851     }
1852     else
1853     {
1854         if(!done_extents)
1855         {
1856             if(flags & ETO_GLYPH_INDEX)
1857                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1858             else
1859                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1860             done_extents = TRUE;
1861         }
1862         width = INTERNAL_XWSTODS(dc, sz.cx);
1863     }
1864     xwidth = width * cosEsc;
1865     ywidth = width * sinEsc;
1866
1867     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1868     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1869     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1870     {
1871     case TA_LEFT:
1872         if (align & TA_UPDATECP)
1873         {
1874             pt.x = x + xwidth;
1875             pt.y = y - ywidth;
1876             DPtoLP(hdc, &pt, 1);
1877             MoveToEx(hdc, pt.x, pt.y, NULL);
1878         }
1879         break;
1880
1881     case TA_CENTER:
1882         x -= xwidth / 2;
1883         y += ywidth / 2;
1884         break;
1885
1886     case TA_RIGHT:
1887         x -= xwidth;
1888         y += ywidth;
1889         if (align & TA_UPDATECP)
1890         {
1891             pt.x = x;
1892             pt.y = y;
1893             DPtoLP(hdc, &pt, 1);
1894             MoveToEx(hdc, pt.x, pt.y, NULL);
1895         }
1896         break;
1897     }
1898
1899     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1900     {
1901     case TA_TOP:
1902         y += tm.tmAscent * cosEsc;
1903         x += tm.tmAscent * sinEsc;
1904         break;
1905
1906     case TA_BOTTOM:
1907         y -= tm.tmDescent * cosEsc;
1908         x -= tm.tmDescent * sinEsc;
1909         break;
1910
1911     case TA_BASELINE:
1912         break;
1913     }
1914
1915     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1916     {
1917         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1918         {
1919             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1920                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1921             {
1922                 RECT rc;
1923                 rc.left = x;
1924                 rc.right = x + width;
1925                 rc.top = y - tm.tmAscent;
1926                 rc.bottom = y + tm.tmDescent;
1927                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1928             }
1929         }
1930     }
1931
1932     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1933     {
1934         HFONT orig_font = dc->hFont, cur_font;
1935         UINT glyph;
1936         INT span = 0, *offsets = NULL, i;
1937
1938         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1939         for(i = 0; i < count; i++)
1940         {
1941             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1942             if(cur_font != dc->hFont)
1943             {
1944                 if(!offsets)
1945                 {
1946                     int j;
1947                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1948                     offsets[0] = 0;
1949                     if(!deltas)
1950                     {
1951                         SIZE tmpsz;
1952                         for(j = 1; j < count; j++)
1953                         {
1954                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1955                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1956                         }
1957                     }
1958                     else
1959                     {
1960                         for(j = 1; j < count; j++)
1961                             offsets[j] = offsets[j-1] + deltas[j];
1962                     }
1963                 }
1964                 if(span)
1965                 {
1966                     if (PATH_IsPathOpen(dc->path))
1967                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1968                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1969                                               glyphs, span, deltas ? deltas + i - span : NULL);
1970                     else
1971                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1972                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1973                                            glyphs, span, deltas ? deltas + i - span : NULL);
1974                     span = 0;
1975                 }
1976                 SelectObject(hdc, cur_font);
1977             }
1978             glyphs[span++] = glyph;
1979
1980             if(i == count - 1)
1981             {
1982                 if (PATH_IsPathOpen(dc->path))
1983                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1984                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
1985                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1986                                           glyphs, span, deltas ? deltas + count - span : NULL);
1987                 else
1988                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1989                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
1990                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1991                                              glyphs, span, deltas ? deltas + count - span : NULL);
1992                 SelectObject(hdc, orig_font);
1993                 HeapFree(GetProcessHeap(), 0, offsets);
1994            }
1995         }
1996     }
1997     else
1998     {
1999         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2000         {
2001             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2002             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2003             flags |= ETO_GLYPH_INDEX;
2004         }
2005
2006         if (PATH_IsPathOpen(dc->path))
2007             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2008                                   glyphs ? glyphs : reordered_str, count, deltas);
2009         else
2010             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2011                                      glyphs ? glyphs : reordered_str, count, deltas);
2012     }
2013
2014 done:
2015     HeapFree(GetProcessHeap(), 0, deltas);
2016     if(glyphs != reordered_str)
2017         HeapFree(GetProcessHeap(), 0, glyphs);
2018     if(reordered_str != str)
2019         HeapFree(GetProcessHeap(), 0, reordered_str);
2020
2021     GDI_ReleaseObj( hdc );
2022
2023     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2024     {
2025         int underlinePos, strikeoutPos;
2026         int underlineWidth, strikeoutWidth;
2027         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2028         OUTLINETEXTMETRICW* otm = NULL;
2029
2030         if(!size)
2031         {
2032             underlinePos = 0;
2033             underlineWidth = tm.tmAscent / 20 + 1;
2034             strikeoutPos = tm.tmAscent / 2;
2035             strikeoutWidth = underlineWidth;
2036         }
2037         else
2038         {
2039             otm = HeapAlloc(GetProcessHeap(), 0, size);
2040             GetOutlineTextMetricsW(hdc, size, otm);
2041             underlinePos = otm->otmsUnderscorePosition;
2042             underlineWidth = otm->otmsUnderscoreSize;
2043             strikeoutPos = otm->otmsStrikeoutPosition;
2044             strikeoutWidth = otm->otmsStrikeoutSize;
2045             HeapFree(GetProcessHeap(), 0, otm);
2046         }
2047
2048         if (PATH_IsPathOpen(dc->path))
2049         {
2050             POINT pts[5];
2051             HPEN hpen;
2052             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2053
2054             hbrush = SelectObject(hdc, hbrush);
2055             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2056
2057             if (lf.lfUnderline)
2058             {
2059                 pts[0].x = x - underlinePos * sinEsc;
2060                 pts[0].y = y - underlinePos * cosEsc;
2061                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2062                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2063                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2064                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2065                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2066                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2067                 pts[4].x = pts[0].x;
2068                 pts[4].y = pts[0].y;
2069                 DPtoLP(hdc, pts, 5);
2070                 Polygon(hdc, pts, 5);
2071             }
2072
2073             if (lf.lfStrikeOut)
2074             {
2075                 pts[0].x = x - strikeoutPos * sinEsc;
2076                 pts[0].y = y - strikeoutPos * cosEsc;
2077                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2078                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2079                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2080                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2081                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2082                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2083                 pts[4].x = pts[0].x;
2084                 pts[4].y = pts[0].y;
2085                 DPtoLP(hdc, pts, 5);
2086                 Polygon(hdc, pts, 5);
2087             }
2088
2089             SelectObject(hdc, hpen);
2090             hbrush = SelectObject(hdc, hbrush);
2091             DeleteObject(hbrush);
2092         }
2093         else
2094         {
2095             POINT pts[2], oldpt;
2096             HPEN hpen;
2097
2098             if (lf.lfUnderline)
2099             {
2100                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2101                 hpen = SelectObject(hdc, hpen);
2102                 pts[0].x = x;
2103                 pts[0].y = y;
2104                 pts[1].x = x + xwidth;
2105                 pts[1].y = y - ywidth;
2106                 DPtoLP(hdc, pts, 2);
2107                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2108                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2109                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2110                 DeleteObject(SelectObject(hdc, hpen));
2111             }
2112
2113             if (lf.lfStrikeOut)
2114             {
2115                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2116                 hpen = SelectObject(hdc, hpen);
2117                 pts[0].x = x;
2118                 pts[0].y = y;
2119                 pts[1].x = x + xwidth;
2120                 pts[1].y = y - ywidth;
2121                 DPtoLP(hdc, pts, 2);
2122                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2123                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2124                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2125                 DeleteObject(SelectObject(hdc, hpen));
2126             }
2127         }
2128     }
2129
2130     return ret;
2131 }
2132
2133
2134 /***********************************************************************
2135  *           TextOutA    (GDI32.@)
2136  */
2137 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2138 {
2139     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2140 }
2141
2142
2143 /***********************************************************************
2144  *           TextOutW    (GDI32.@)
2145  */
2146 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2147 {
2148     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2149 }
2150
2151
2152 /***********************************************************************
2153  *              PolyTextOutA (GDI32.@)
2154  *
2155  * See PolyTextOutW.
2156  */
2157 BOOL WINAPI PolyTextOutA ( HDC hdc,               /* [in] Handle to device context */
2158                            PPOLYTEXTA pptxt,      /* [in] Array of strings */
2159                            INT cStrings )         /* [in] Number of strings in array */
2160 {
2161     for (; cStrings>0; cStrings--, pptxt++)
2162         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2163             return FALSE;
2164     return TRUE;
2165 }
2166
2167
2168
2169 /***********************************************************************
2170  *              PolyTextOutW (GDI32.@)
2171  *
2172  * Draw several Strings
2173  *
2174  * RETURNS
2175  *  TRUE:  Success.
2176  *  FALSE: Failure.
2177  */
2178 BOOL WINAPI PolyTextOutW ( HDC hdc,               /* [in] Handle to device context */
2179                            PPOLYTEXTW pptxt,      /* [in] Array of strings */
2180                            INT cStrings )         /* [in] Number of strings in array */
2181 {
2182     for (; cStrings>0; cStrings--, pptxt++)
2183         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2184             return FALSE;
2185     return TRUE;
2186 }
2187
2188
2189 /* FIXME: all following APIs ******************************************/
2190
2191
2192 /***********************************************************************
2193  *           SetMapperFlags    (GDI32.@)
2194  */
2195 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2196 {
2197     DC *dc = DC_GetDCPtr( hDC );
2198     DWORD ret = 0;
2199     if(!dc) return 0;
2200     if(dc->funcs->pSetMapperFlags)
2201     {
2202         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2203         /* FIXME: ret is just a success flag, we should return a proper value */
2204     }
2205     else
2206         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2207     GDI_ReleaseObj( hDC );
2208     return ret;
2209 }
2210
2211 /***********************************************************************
2212  *          GetAspectRatioFilterEx  (GDI.486)
2213  */
2214 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2215 {
2216   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2217   return FALSE;
2218 }
2219
2220 /***********************************************************************
2221  *          GetAspectRatioFilterEx  (GDI32.@)
2222  */
2223 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2224 {
2225   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2226   return FALSE;
2227 }
2228
2229
2230 /***********************************************************************
2231  *           GetCharABCWidthsA   (GDI32.@)
2232  *
2233  * See GetCharABCWidthsW.
2234  */
2235 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2236                                   LPABC abc )
2237 {
2238     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2239     LPSTR str;
2240     LPWSTR wstr;
2241     BOOL ret = TRUE;
2242
2243     if(count <= 0) return FALSE;
2244
2245     str = HeapAlloc(GetProcessHeap(), 0, count);
2246     for(i = 0; i < count; i++)
2247         str[i] = (BYTE)(firstChar + i);
2248
2249     wstr = FONT_mbtowc(str, count, &wlen);
2250
2251     for(i = 0; i < wlen; i++)
2252     {
2253         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2254         {
2255             ret = FALSE;
2256             break;
2257         }
2258         abc++;
2259     }
2260
2261     HeapFree(GetProcessHeap(), 0, str);
2262     HeapFree(GetProcessHeap(), 0, wstr);
2263
2264     return ret;
2265 }
2266
2267
2268 /******************************************************************************
2269  * GetCharABCWidthsW [GDI32.@]
2270  *
2271  * Retrieves widths of characters in range.
2272  *
2273  * PARAMS
2274  *    hdc       [I] Handle of device context
2275  *    firstChar [I] First character in range to query
2276  *    lastChar  [I] Last character in range to query
2277  *    abc       [O] Address of character-width structure
2278  *
2279  * NOTES
2280  *    Only works with TrueType fonts
2281  *
2282  * RETURNS
2283  *    Success: TRUE
2284  *    Failure: FALSE
2285  */
2286 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2287                                    LPABC abc )
2288 {
2289     DC *dc = DC_GetDCPtr(hdc);
2290     unsigned int i;
2291     BOOL ret = FALSE;
2292
2293     if (!dc) return FALSE;
2294
2295     if(dc->gdiFont)
2296         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2297     else
2298         FIXME(": stub\n");
2299
2300     if (ret)
2301     {
2302         /* convert device units to logical */
2303         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2304             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2305             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2306             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2307         }
2308         ret = TRUE;
2309     }
2310
2311     GDI_ReleaseObj(hdc);
2312     return ret;
2313 }
2314
2315
2316 /******************************************************************************
2317  * GetCharABCWidthsI [GDI32.@]
2318  *
2319  * Retrieves widths of characters in range.
2320  *
2321  * PARAMS
2322  *    hdc       [I] Handle of device context
2323  *    firstChar [I] First glyphs in range to query
2324  *    count     [I] Last glyphs in range to query
2325  *    pgi       [i] Array of glyphs to query
2326  *    abc       [O] Address of character-width structure
2327  *
2328  * NOTES
2329  *    Only works with TrueType fonts
2330  *
2331  * RETURNS
2332  *    Success: TRUE
2333  *    Failure: FALSE
2334  */
2335 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2336                                LPWORD pgi, LPABC abc)
2337 {
2338     DC *dc = DC_GetDCPtr(hdc);
2339     unsigned int i;
2340     BOOL ret = FALSE;
2341
2342     if (!dc) return FALSE;
2343
2344     if(dc->gdiFont)
2345         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2346     else
2347         FIXME(": stub\n");
2348
2349     if (ret)
2350     {
2351         /* convert device units to logical */
2352         for( i = firstChar; i <= count; i++, abc++ ) {
2353             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2354             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2355             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2356         }
2357         ret = TRUE;
2358     }
2359
2360     GDI_ReleaseObj(hdc);
2361     return ret;
2362 }
2363
2364
2365 /***********************************************************************
2366  *           GetGlyphOutlineA    (GDI32.@)
2367  */
2368 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2369                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2370                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2371 {
2372     LPWSTR p = NULL;
2373     DWORD ret;
2374     UINT c;
2375
2376     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2377         int len;
2378         char mbchs[2];
2379         if(uChar > 0xff) { /* but, 2 bytes character only */
2380             len = 2;
2381             mbchs[0] = (uChar & 0xff00) >> 8;
2382             mbchs[1] = (uChar & 0xff);
2383         } else {
2384             len = 1;
2385             mbchs[0] = (uChar & 0xff);
2386         }
2387         p = FONT_mbtowc(mbchs, len, NULL);
2388         c = p[0];
2389     } else
2390         c = uChar;
2391     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2392                            lpmat2);
2393     HeapFree(GetProcessHeap(), 0, p);
2394     return ret;
2395 }
2396
2397 /***********************************************************************
2398  *           GetGlyphOutlineW    (GDI32.@)
2399  */
2400 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2401                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2402                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2403 {
2404     DC *dc = DC_GetDCPtr(hdc);
2405     DWORD ret;
2406
2407     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2408           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2409
2410     if(!dc) return GDI_ERROR;
2411
2412     if(dc->gdiFont)
2413       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2414                                    cbBuffer, lpBuffer, lpmat2);
2415     else
2416       ret = GDI_ERROR;
2417
2418     GDI_ReleaseObj(hdc);
2419     return ret;
2420 }
2421
2422
2423 /***********************************************************************
2424  *           CreateScalableFontResourceA   (GDI32.@)
2425  */
2426 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2427                                              LPCSTR lpszResourceFile,
2428                                              LPCSTR lpszFontFile,
2429                                              LPCSTR lpszCurrentPath )
2430 {
2431     HANDLE f;
2432
2433     /* fHidden=1 - only visible for the calling app, read-only, not
2434      * enumbered with EnumFonts/EnumFontFamilies
2435      * lpszCurrentPath can be NULL
2436      */
2437     FIXME("(%ld,%s,%s,%s): stub\n",
2438           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2439           debugstr_a(lpszCurrentPath) );
2440
2441     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2442     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2443         CloseHandle(f);
2444         SetLastError(ERROR_FILE_EXISTS);
2445         return FALSE;
2446     }
2447     return FALSE; /* create failed */
2448 }
2449
2450 /***********************************************************************
2451  *           CreateScalableFontResourceW   (GDI32.@)
2452  */
2453 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2454                                              LPCWSTR lpszResourceFile,
2455                                              LPCWSTR lpszFontFile,
2456                                              LPCWSTR lpszCurrentPath )
2457 {
2458     FIXME("(%ld,%p,%p,%p): stub\n",
2459           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2460     return FALSE; /* create failed */
2461 }
2462
2463 /*************************************************************************
2464  *             GetKerningPairsA   (GDI32.@)
2465  */
2466 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2467                                LPKERNINGPAIR lpKerningPairs )
2468 {
2469     return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2470 }
2471
2472
2473 /*************************************************************************
2474  *             GetKerningPairsW   (GDI32.@)
2475  */
2476 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2477                                  LPKERNINGPAIR lpKerningPairs )
2478 {
2479     unsigned int i;
2480     FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2481
2482     if(!lpKerningPairs) /* return the number of kerning pairs */
2483         return 0;
2484
2485     for (i = 0; i < cPairs; i++)
2486         lpKerningPairs[i].iKernAmount = 0;
2487     return 0;
2488 }
2489
2490 /*************************************************************************
2491  * TranslateCharsetInfo [GDI32.@]
2492  *
2493  * Fills a CHARSETINFO structure for a character set, code page, or
2494  * font. This allows making the correspondance between different labelings
2495  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2496  * of the same encoding.
2497  *
2498  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2499  * only one codepage should be set in *lpSrc.
2500  *
2501  * RETURNS
2502  *   TRUE on success, FALSE on failure.
2503  *
2504  */
2505 BOOL WINAPI TranslateCharsetInfo(
2506   LPDWORD lpSrc, /* [in]
2507        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2508        if flags == TCI_SRCCHARSET: a character set value
2509        if flags == TCI_SRCCODEPAGE: a code page value
2510                  */
2511   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2512   DWORD flags /* [in] determines interpretation of lpSrc */)
2513 {
2514     int index = 0;
2515     switch (flags) {
2516     case TCI_SRCFONTSIG:
2517         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2518       break;
2519     case TCI_SRCCODEPAGE:
2520       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2521       break;
2522     case TCI_SRCCHARSET:
2523       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2524       break;
2525     default:
2526       return FALSE;
2527     }
2528     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2529     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2530     return TRUE;
2531 }
2532
2533 /*************************************************************************
2534  *             GetFontLanguageInfo   (GDI32.@)
2535  */
2536 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2537 {
2538         FONTSIGNATURE fontsig;
2539         static const DWORD GCP_DBCS_MASK=0x003F0000,
2540                 GCP_DIACRITIC_MASK=0x00000000,
2541                 FLI_GLYPHS_MASK=0x00000000,
2542                 GCP_GLYPHSHAPE_MASK=0x00000040,
2543                 GCP_KASHIDA_MASK=0x00000000,
2544                 GCP_LIGATE_MASK=0x00000000,
2545                 GCP_USEKERNING_MASK=0x00000000,
2546                 GCP_REORDER_MASK=0x00000060;
2547
2548         DWORD result=0;
2549
2550         GetTextCharsetInfo( hdc, &fontsig, 0 );
2551         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2552
2553         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2554                 result|=GCP_DBCS;
2555
2556         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2557                 result|=GCP_DIACRITIC;
2558
2559         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2560                 result|=FLI_GLYPHS;
2561
2562         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2563                 result|=GCP_GLYPHSHAPE;
2564
2565         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2566                 result|=GCP_KASHIDA;
2567
2568         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2569                 result|=GCP_LIGATE;
2570
2571         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2572                 result|=GCP_USEKERNING;
2573
2574         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2575         if( GetTextAlign( hdc) & TA_RTLREADING )
2576             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2577                     result|=GCP_REORDER;
2578
2579         return result;
2580 }
2581
2582
2583 /*************************************************************************
2584  * GetFontData [GDI32.@]
2585  *
2586  * Retrieve data for TrueType font.
2587  *
2588  * RETURNS
2589  *
2590  * success: Number of bytes returned
2591  * failure: GDI_ERROR
2592  *
2593  * NOTES
2594  *
2595  * Calls SetLastError()
2596  *
2597  */
2598 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2599     LPVOID buffer, DWORD length)
2600 {
2601     DC *dc = DC_GetDCPtr(hdc);
2602     DWORD ret = GDI_ERROR;
2603
2604     if(!dc) return GDI_ERROR;
2605
2606     if(dc->gdiFont)
2607       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2608
2609     GDI_ReleaseObj(hdc);
2610     return ret;
2611 }
2612
2613 /*************************************************************************
2614  * GetGlyphIndicesA [GDI32.@]
2615  */
2616 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2617                               LPWORD pgi, DWORD flags)
2618 {
2619     DWORD ret;
2620     WCHAR *lpstrW;
2621     INT countW;
2622
2623     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2624           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2625
2626     lpstrW = FONT_mbtowc(lpstr, count, &countW);
2627     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2628     HeapFree(GetProcessHeap(), 0, lpstrW);
2629
2630     return ret;
2631 }
2632
2633 /*************************************************************************
2634  * GetGlyphIndicesW [GDI32.@]
2635  */
2636 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2637                               LPWORD pgi, DWORD flags)
2638 {
2639     DC *dc = DC_GetDCPtr(hdc);
2640     DWORD ret = GDI_ERROR;
2641
2642     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2643           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2644
2645     if(!dc) return GDI_ERROR;
2646
2647     if(dc->gdiFont)
2648         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2649
2650     GDI_ReleaseObj(hdc);
2651     return ret;
2652 }
2653
2654 /*************************************************************************
2655  * GetCharacterPlacementA [GDI32.@]
2656  *
2657  * See GetCharacterPlacementW.
2658  *
2659  * NOTES:
2660  *  the web browser control of ie4 calls this with dwFlags=0
2661  */
2662 DWORD WINAPI
2663 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2664                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2665                          DWORD dwFlags)
2666 {
2667     WCHAR *lpStringW;
2668     INT uCountW;
2669     GCP_RESULTSW resultsW;
2670     DWORD ret;
2671
2672     TRACE("%s, %d, %d, 0x%08lx\n",
2673           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2674
2675     /* both structs are equal in size */
2676     memcpy(&resultsW, lpResults, sizeof(resultsW));
2677
2678     lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2679     if(lpResults->lpOutString)
2680         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2681
2682     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2683
2684     lpResults->nGlyphs = resultsW.nGlyphs;
2685     lpResults->nMaxFit = resultsW.nMaxFit;
2686
2687     if(lpResults->lpOutString) {
2688         WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2689                             lpResults->lpOutString, uCount, NULL, NULL );
2690     }
2691
2692     HeapFree(GetProcessHeap(), 0, lpStringW);
2693     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2694
2695     return ret;
2696 }
2697
2698 /*************************************************************************
2699  * GetCharacterPlacementW [GDI32.@]
2700  *
2701  *   Retrieve information about a string. This includes the width, reordering,
2702  *   Glyphing and so on.
2703  *
2704  * RETURNS
2705  *
2706  *   The width and height of the string if successful, 0 if failed.
2707  *
2708  * BUGS
2709  *
2710  *   All flags except GCP_REORDER are not yet implemented.
2711  *   Reordering is not 100% complient to the Windows BiDi method.
2712  *   Caret positioning is not yet implemented for BiDi.
2713  *   Classes are not yet implemented.
2714  *
2715  */
2716 DWORD WINAPI
2717 GetCharacterPlacementW(
2718                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2719                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2720                 INT uCount,             /* [in] Number of WORDS in string. */
2721                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2722                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2723                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2724                 )
2725 {
2726     DWORD ret=0;
2727     SIZE size;
2728     UINT i, nSet;
2729
2730     TRACE("%s, %d, %d, 0x%08lx\n",
2731           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2732
2733     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2734           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2735             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2736             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2737             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2738
2739     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
2740     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2741     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2742         FIXME("Caret positions for complex scripts not implemented\n");
2743
2744         nSet = (UINT)uCount;
2745         if(nSet > lpResults->nGlyphs)
2746                 nSet = lpResults->nGlyphs;
2747
2748         /* return number of initialized fields */
2749         lpResults->nGlyphs = nSet;
2750
2751         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2752         {
2753                 /* Treat the case where no special handling was requested in a fastpath way */
2754                 /* copy will do if the GCP_REORDER flag is not set */
2755                 if(lpResults->lpOutString)
2756                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2757
2758                 if(lpResults->lpOrder)
2759                 {
2760                         for(i = 0; i < nSet; i++)
2761                                 lpResults->lpOrder[i] = i;
2762                 }
2763         } else
2764         {
2765             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2766                           nSet, lpResults->lpOrder );
2767         }
2768
2769         /* FIXME: Will use the placement chars */
2770         if (lpResults->lpDx)
2771         {
2772                 int c;
2773                 for (i = 0; i < nSet; i++)
2774                 {
2775                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2776                                 lpResults->lpDx[i]= c;
2777                 }
2778         }
2779
2780     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2781     {
2782         int pos = 0;
2783        
2784         lpResults->lpCaretPos[0] = 0;
2785         for (i = 1; i < nSet; i++)
2786             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2787                 lpResults->lpCaretPos[i] = (pos += size.cx);
2788     }
2789    
2790     if(lpResults->lpGlyphs)
2791         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2792
2793     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2794       ret = MAKELONG(size.cx, size.cy);
2795
2796     return ret;
2797 }
2798
2799 /*************************************************************************
2800  *      GetCharABCWidthsFloatA [GDI32.@]
2801  *
2802  * See GetCharABCWidthsFloatW.
2803  */
2804 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2805 {
2806     INT i, wlen, count = (INT)(last - first + 1);
2807     LPSTR str;
2808     LPWSTR wstr;
2809     BOOL ret = TRUE;
2810
2811     if (count <= 0) return FALSE;
2812
2813     str = HeapAlloc(GetProcessHeap(), 0, count);
2814
2815     for(i = 0; i < count; i++)
2816         str[i] = (BYTE)(first + i);
2817
2818     wstr = FONT_mbtowc(str, count, &wlen);
2819
2820     for (i = 0; i < wlen; i++)
2821     {
2822         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2823         {
2824             ret = FALSE;
2825             break;
2826         }
2827         abcf++;
2828     }
2829
2830     HeapFree( GetProcessHeap(), 0, str );
2831     HeapFree( GetProcessHeap(), 0, wstr );
2832
2833     return ret;
2834 }
2835
2836 /*************************************************************************
2837  *      GetCharABCWidthsFloatW [GDI32.@]
2838  *
2839  * Retrieves widths of a range of characters.
2840  *
2841  * PARAMS
2842  *    hdc   [I] Handle to device context.
2843  *    first [I] First character in range to query.
2844  *    last  [I] Last character in range to query.
2845  *    abcf  [O] Array of LPABCFLOAT structures.
2846  *
2847  * RETURNS
2848  *    Success: TRUE
2849  *    Failure: FALSE
2850  *
2851  * BUGS
2852  *    Only works with TrueType fonts. It also doesn't return real
2853  *    floats but converted integers because it's implemented on
2854  *    top of GetCharABCWidthsW.
2855  */
2856 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2857 {
2858     ABC *abc;
2859     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2860     BOOL ret;
2861
2862     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2863
2864     abc = HeapAlloc( GetProcessHeap(), 0, size );
2865     if (!abc) return FALSE;
2866
2867     ret = GetCharABCWidthsW( hdc, first, last, abc );
2868     if (ret == TRUE)
2869     {
2870         for (i = first; i <= last; i++, abc++, abcf++)
2871         {
2872             abcf->abcfA = abc->abcA;
2873             abcf->abcfB = abc->abcB;
2874             abcf->abcfC = abc->abcC;
2875         }
2876     }
2877     HeapFree( GetProcessHeap(), 0, abc );
2878     return ret;
2879 }
2880
2881 /*************************************************************************
2882  *      GetCharWidthFloatA [GDI32.@]
2883  */
2884 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2885                                     UINT iLastChar, PFLOAT pxBuffer)
2886 {
2887        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2888        return 0;
2889 }
2890
2891 /*************************************************************************
2892  *      GetCharWidthFloatW [GDI32.@]
2893  */
2894 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2895                                     UINT iLastChar, PFLOAT pxBuffer)
2896 {
2897        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2898        return 0;
2899 }
2900
2901
2902 /***********************************************************************
2903  *                                                                     *
2904  *           Font Resource API                                         *
2905  *                                                                     *
2906  ***********************************************************************/
2907
2908 /***********************************************************************
2909  *           AddFontResourceA    (GDI32.@)
2910  */
2911 INT WINAPI AddFontResourceA( LPCSTR str )
2912 {
2913     return AddFontResourceExA( str, 0, NULL);
2914 }
2915
2916 /***********************************************************************
2917  *           AddFontResourceW    (GDI32.@)
2918  */
2919 INT WINAPI AddFontResourceW( LPCWSTR str )
2920 {
2921     return AddFontResourceExW(str, 0, NULL);
2922 }
2923
2924
2925 /***********************************************************************
2926  *           AddFontResourceExA    (GDI32.@)
2927  */
2928 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2929 {
2930     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2931     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2932     INT ret;
2933
2934     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2935     ret = AddFontResourceExW(strW, fl, pdv);
2936     HeapFree(GetProcessHeap(), 0, strW);
2937     return ret;
2938 }
2939
2940 /***********************************************************************
2941  *           AddFontResourceExW    (GDI32.@)
2942  */
2943 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2944 {
2945     return WineEngAddFontResourceEx(str, fl, pdv);
2946 }
2947
2948 /***********************************************************************
2949  *           RemoveFontResourceA    (GDI32.@)
2950  */
2951 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2952 {
2953     return RemoveFontResourceExA(str, 0, 0);
2954 }
2955
2956 /***********************************************************************
2957  *           RemoveFontResourceW    (GDI32.@)
2958  */
2959 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2960 {
2961     return RemoveFontResourceExW(str, 0, 0);
2962 }
2963
2964 /***********************************************************************
2965  *           AddFontMemResourceEx    (GDI32.@)
2966  */
2967 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2968 {
2969     FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
2970     return NULL;
2971 }
2972
2973 /***********************************************************************
2974  *           RemoveFontResourceExA    (GDI32.@)
2975  */
2976 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2977 {
2978     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2979     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2980     INT ret;
2981
2982     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2983     ret = RemoveFontResourceExW(strW, fl, pdv);
2984     HeapFree(GetProcessHeap(), 0, strW);
2985     return ret;
2986 }
2987
2988 /***********************************************************************
2989  *           RemoveFontResourceExW    (GDI32.@)
2990  */
2991 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2992 {
2993     return WineEngRemoveFontResourceEx(str, fl, pdv);
2994 }
2995
2996 /***********************************************************************
2997  *           GetTextCharset    (GDI32.@)
2998  */
2999 UINT WINAPI GetTextCharset(HDC hdc)
3000 {
3001     /* MSDN docs say this is equivalent */
3002     return GetTextCharsetInfo(hdc, NULL, 0);
3003 }
3004
3005 /***********************************************************************
3006  *           GetTextCharsetInfo    (GDI32.@)
3007  */
3008 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3009 {
3010     UINT ret = DEFAULT_CHARSET;
3011     DC *dc = DC_GetDCPtr(hdc);
3012
3013     if (!dc) goto done;
3014
3015     if (dc->gdiFont)
3016         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3017
3018     GDI_ReleaseObj(hdc);
3019
3020 done:
3021     if (ret == DEFAULT_CHARSET && fs)
3022         memset(fs, 0, sizeof(FONTSIGNATURE));
3023     return ret;
3024 }
3025
3026 /***********************************************************************
3027  *           GdiGetCharDimensions    (GDI32.@)
3028  *
3029  * Gets the average width of the characters in the English alphabet.
3030  *
3031  * PARAMS
3032  *  hdc    [I] Handle to the device context to measure on.
3033  *  lptm   [O] Pointer to memory to store the text metrics into.
3034  *  height [O] On exit, the maximum height of characters in the English alphabet.
3035  *
3036  * RETURNS
3037  *  The average width of characters in the English alphabet.
3038  *
3039  * NOTES
3040  *  This function is used by the dialog manager to get the size of a dialog
3041  *  unit. It should also be used by other pieces of code that need to know
3042  *  the size of a dialog unit in logical units without having access to the
3043  *  window handle of the dialog.
3044  *  Windows caches the font metrics from this function, but we don't and
3045  *  there doesn't appear to be an immediate advantage to do so.
3046  *
3047  * SEE ALSO
3048  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3049  */
3050 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3051 {
3052     SIZE sz;
3053     static const WCHAR alphabet[] = {
3054         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3055         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3056         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3057
3058     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3059
3060     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3061
3062     if (height) *height = sz.cy;
3063     return (sz.cx / 26 + 1) / 2;
3064 }
3065
3066 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3067 {
3068     FIXME("(%d): stub\n", fEnableEUDC);
3069     return FALSE;
3070 }