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