Fixed other bugs within MMIO implementation. Now, it's possible to
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include "wine/winestring.h"
11 #include "font.h"
12 #include "heap.h"
13 #include "metafile.h"
14 #include "options.h"
15 #include "debugtools.h"
16 #include "winerror.h"
17 #include "dc.h"
18 #include "winnls.h"
19
20 DEFAULT_DEBUG_CHANNEL(font)
21 DECLARE_DEBUG_CHANNEL(gdi)
22
23 #define ENUM_UNICODE    0x00000001
24
25 typedef struct
26 {
27   LPLOGFONT16           lpLogFontParam;
28   FONTENUMPROCEX16      lpEnumFunc;
29   LPARAM                lpData;
30
31   LPNEWTEXTMETRICEX16   lpTextMetric;
32   LPENUMLOGFONTEX16     lpLogFont;
33   SEGPTR                segTextMetric;
34   SEGPTR                segLogFont;
35 } fontEnum16;
36
37 typedef struct
38 {
39   LPLOGFONTW          lpLogFontParam;
40   FONTENUMPROCEXW     lpEnumFunc;
41   LPARAM                lpData;
42
43   LPNEWTEXTMETRICEXW  lpTextMetric;
44   LPENUMLOGFONTEXW    lpLogFont;
45   DWORD                 dwFlags;
46 } fontEnum32;
47  
48 /*
49  *  For TranslateCharsetInfo
50  */
51 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
52 #define MAXTCIINDEX 32
53 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
54   /* ANSI */
55   { ANSI_CHARSET, 1252, FS(0)},
56   { EASTEUROPE_CHARSET, 1250, FS(1)},
57   { RUSSIAN_CHARSET, 1251, FS(2)},
58   { GREEK_CHARSET, 1253, FS(3)},
59   { TURKISH_CHARSET, 1254, FS(4)},
60   { HEBREW_CHARSET, 1255, FS(5)},
61   { ARABIC_CHARSET, 1256, FS(6)},
62   { BALTIC_CHARSET, 1257, FS(7)},
63   /* reserved by ANSI */
64   { DEFAULT_CHARSET, 0, FS(0)},
65   { DEFAULT_CHARSET, 0, FS(0)},
66   { DEFAULT_CHARSET, 0, FS(0)},
67   { DEFAULT_CHARSET, 0, FS(0)},
68   { DEFAULT_CHARSET, 0, FS(0)},
69   { DEFAULT_CHARSET, 0, FS(0)},
70   { DEFAULT_CHARSET, 0, FS(0)},
71   { DEFAULT_CHARSET, 0, FS(0)},
72   /* ANSI and OEM */
73   { THAI_CHARSET,  874,  FS(16)},
74   { SHIFTJIS_CHARSET, 932, FS(17)},
75   { GB2312_CHARSET, 936, FS(18)},
76   { HANGEUL_CHARSET, 949, FS(19)},
77   { CHINESEBIG5_CHARSET, 950, FS(20)},
78   { JOHAB_CHARSET, 1361, FS(21)}, 
79   /* reserved for alternate ANSI and OEM */
80   { DEFAULT_CHARSET, 0, FS(0)},
81   { DEFAULT_CHARSET, 0, FS(0)},
82   { DEFAULT_CHARSET, 0, FS(0)},
83   { DEFAULT_CHARSET, 0, FS(0)},
84   { DEFAULT_CHARSET, 0, FS(0)},
85   { DEFAULT_CHARSET, 0, FS(0)},
86   { DEFAULT_CHARSET, 0, FS(0)},
87   { DEFAULT_CHARSET, 0, FS(0)},
88   /* reserved for system */
89   { DEFAULT_CHARSET, 0, FS(0)},
90   { DEFAULT_CHARSET, 0, FS(0)},
91 };
92
93 /***********************************************************************
94  *              LOGFONT conversion functions.
95  */
96 void FONT_LogFont32ATo16( const LOGFONTA* font32, LPLOGFONT16 font16 )
97 {
98     font16->lfHeight = font32->lfHeight;
99     font16->lfWidth = font32->lfWidth;
100     font16->lfEscapement = font32->lfEscapement;
101     font16->lfOrientation = font32->lfOrientation;
102     font16->lfWeight = font32->lfWeight;
103     font16->lfItalic = font32->lfItalic;
104     font16->lfUnderline = font32->lfUnderline;
105     font16->lfStrikeOut = font32->lfStrikeOut;
106     font16->lfCharSet = font32->lfCharSet;
107     font16->lfOutPrecision = font32->lfOutPrecision;
108     font16->lfClipPrecision = font32->lfClipPrecision;
109     font16->lfQuality = font32->lfQuality;
110     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
111     lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
112 }
113
114 void FONT_LogFont32WTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
115 {
116     font16->lfHeight = font32->lfHeight;
117     font16->lfWidth = font32->lfWidth;
118     font16->lfEscapement = font32->lfEscapement;
119     font16->lfOrientation = font32->lfOrientation;
120     font16->lfWeight = font32->lfWeight;
121     font16->lfItalic = font32->lfItalic;
122     font16->lfUnderline = font32->lfUnderline;
123     font16->lfStrikeOut = font32->lfStrikeOut;
124     font16->lfCharSet = font32->lfCharSet;
125     font16->lfOutPrecision = font32->lfOutPrecision;
126     font16->lfClipPrecision = font32->lfClipPrecision;
127     font16->lfQuality = font32->lfQuality;
128     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
129     lstrcpynWtoA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
130 }
131
132 void FONT_LogFont16To32A( const LPLOGFONT16 font16, LPLOGFONTA font32 )
133 {
134     font32->lfHeight = font16->lfHeight;
135     font32->lfWidth = font16->lfWidth;
136     font32->lfEscapement = font16->lfEscapement;
137     font32->lfOrientation = font16->lfOrientation;
138     font32->lfWeight = font16->lfWeight;
139     font32->lfItalic = font16->lfItalic;
140     font32->lfUnderline = font16->lfUnderline;
141     font32->lfStrikeOut = font16->lfStrikeOut;
142     font32->lfCharSet = font16->lfCharSet;
143     font32->lfOutPrecision = font16->lfOutPrecision;
144     font32->lfClipPrecision = font16->lfClipPrecision;
145     font32->lfQuality = font16->lfQuality;
146     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
147     lstrcpynA( font32->lfFaceName, font16->lfFaceName, LF_FACESIZE );
148 }
149
150 void FONT_LogFont16To32W( const LPLOGFONT16 font16, LPLOGFONTW font32 )
151 {
152     font32->lfHeight = font16->lfHeight;
153     font32->lfWidth = font16->lfWidth;
154     font32->lfEscapement = font16->lfEscapement;
155     font32->lfOrientation = font16->lfOrientation;
156     font32->lfWeight = font16->lfWeight;
157     font32->lfItalic = font16->lfItalic;
158     font32->lfUnderline = font16->lfUnderline;
159     font32->lfStrikeOut = font16->lfStrikeOut;
160     font32->lfCharSet = font16->lfCharSet;
161     font32->lfOutPrecision = font16->lfOutPrecision;
162     font32->lfClipPrecision = font16->lfClipPrecision;
163     font32->lfQuality = font16->lfQuality;
164     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
165     lstrcpynAtoW( font32->lfFaceName, font16->lfFaceName, LF_FACESIZE );
166 }
167
168 void FONT_EnumLogFontEx16To32A( const LPENUMLOGFONTEX16 font16, LPENUMLOGFONTEXA font32 )
169 {
170     FONT_LogFont16To32A( (LPLOGFONT16)font16, (LPLOGFONTA)font32);
171     lstrcpynA( font32->elfFullName, font16->elfFullName, LF_FULLFACESIZE );
172     lstrcpynA( font32->elfStyle, font16->elfStyle, LF_FACESIZE );
173     lstrcpynA( font32->elfScript, font16->elfScript, LF_FACESIZE );
174 }
175
176 void FONT_EnumLogFontEx16To32W( const LPENUMLOGFONTEX16 font16, LPENUMLOGFONTEXW font32 )
177 {
178     FONT_LogFont16To32W( (LPLOGFONT16)font16, (LPLOGFONTW)font32);
179     lstrcpynAtoW( font32->elfFullName, font16->elfFullName, LF_FULLFACESIZE );
180     lstrcpynAtoW( font32->elfStyle, font16->elfStyle, LF_FACESIZE );
181     lstrcpynAtoW( font32->elfScript, font16->elfScript, LF_FACESIZE );
182 }
183
184 /***********************************************************************
185  *              TEXTMETRIC conversion functions.
186  */
187 void FONT_TextMetric32Ato16(const LPTEXTMETRICA ptm32, LPTEXTMETRIC16 ptm16 )
188 {
189     ptm16->tmHeight = ptm32->tmHeight;
190     ptm16->tmAscent = ptm32->tmAscent;
191     ptm16->tmDescent = ptm32->tmDescent;
192     ptm16->tmInternalLeading = ptm32->tmInternalLeading;
193     ptm16->tmExternalLeading = ptm32->tmExternalLeading;
194     ptm16->tmAveCharWidth = ptm32->tmAveCharWidth;
195     ptm16->tmMaxCharWidth = ptm32->tmMaxCharWidth;
196     ptm16->tmWeight = ptm32->tmWeight;
197     ptm16->tmOverhang = ptm32->tmOverhang;
198     ptm16->tmDigitizedAspectX = ptm32->tmDigitizedAspectX;
199     ptm16->tmDigitizedAspectY = ptm32->tmDigitizedAspectY;
200     ptm16->tmFirstChar = ptm32->tmFirstChar;
201     ptm16->tmLastChar = ptm32->tmLastChar;
202     ptm16->tmDefaultChar = ptm32->tmDefaultChar;
203     ptm16->tmBreakChar = ptm32->tmBreakChar;
204     ptm16->tmItalic = ptm32->tmItalic;
205     ptm16->tmUnderlined = ptm32->tmUnderlined;
206     ptm16->tmStruckOut = ptm32->tmStruckOut;
207     ptm16->tmPitchAndFamily = ptm32->tmPitchAndFamily;
208     ptm16->tmCharSet = ptm32->tmCharSet;
209 }
210
211 void FONT_TextMetric32Wto16(const LPTEXTMETRICW ptm32, LPTEXTMETRIC16 ptm16 )
212 {
213     ptm16->tmHeight = ptm32->tmHeight;
214     ptm16->tmAscent = ptm32->tmAscent;
215     ptm16->tmDescent = ptm32->tmDescent;
216     ptm16->tmInternalLeading = ptm32->tmInternalLeading;
217     ptm16->tmExternalLeading = ptm32->tmExternalLeading;
218     ptm16->tmAveCharWidth = ptm32->tmAveCharWidth;
219     ptm16->tmMaxCharWidth = ptm32->tmMaxCharWidth;
220     ptm16->tmWeight = ptm32->tmWeight;
221     ptm16->tmOverhang = ptm32->tmOverhang;
222     ptm16->tmDigitizedAspectX = ptm32->tmDigitizedAspectX;
223     ptm16->tmDigitizedAspectY = ptm32->tmDigitizedAspectY;
224     ptm16->tmFirstChar = ptm32->tmFirstChar;
225     ptm16->tmLastChar = ptm32->tmLastChar;
226     ptm16->tmDefaultChar = ptm32->tmDefaultChar;
227     ptm16->tmBreakChar = ptm32->tmBreakChar;
228     ptm16->tmItalic = ptm32->tmItalic;
229     ptm16->tmUnderlined = ptm32->tmUnderlined;
230     ptm16->tmStruckOut = ptm32->tmStruckOut;
231     ptm16->tmPitchAndFamily = ptm32->tmPitchAndFamily;
232     ptm16->tmCharSet = ptm32->tmCharSet;
233 }
234
235 void FONT_TextMetric16to32A(const LPTEXTMETRIC16 ptm16, LPTEXTMETRICA ptm32 )
236 {
237     ptm32->tmHeight = ptm16->tmHeight;
238     ptm32->tmAscent = ptm16->tmAscent;
239     ptm32->tmDescent = ptm16->tmDescent;
240     ptm32->tmInternalLeading = ptm16->tmInternalLeading;
241     ptm32->tmExternalLeading = ptm16->tmExternalLeading;
242     ptm32->tmAveCharWidth = ptm16->tmAveCharWidth;
243     ptm32->tmMaxCharWidth = ptm16->tmMaxCharWidth;
244     ptm32->tmWeight = ptm16->tmWeight;
245     ptm32->tmOverhang = ptm16->tmOverhang;
246     ptm32->tmDigitizedAspectX = ptm16->tmDigitizedAspectX;
247     ptm32->tmDigitizedAspectY = ptm16->tmDigitizedAspectY;
248     ptm32->tmFirstChar = ptm16->tmFirstChar;
249     ptm32->tmLastChar = ptm16->tmLastChar;
250     ptm32->tmDefaultChar = ptm16->tmDefaultChar;
251     ptm32->tmBreakChar = ptm16->tmBreakChar;
252     ptm32->tmItalic = ptm16->tmItalic;
253     ptm32->tmUnderlined = ptm16->tmUnderlined;
254     ptm32->tmStruckOut = ptm16->tmStruckOut;
255     ptm32->tmPitchAndFamily = ptm16->tmPitchAndFamily;
256     ptm32->tmCharSet = ptm16->tmCharSet;
257 }
258
259 void FONT_TextMetric16to32W(const LPTEXTMETRIC16 ptm16, LPTEXTMETRICW ptm32 )
260 {
261     ptm32->tmHeight = ptm16->tmHeight;
262     ptm32->tmAscent = ptm16->tmAscent;
263     ptm32->tmDescent = ptm16->tmDescent;
264     ptm32->tmInternalLeading = ptm16->tmInternalLeading;
265     ptm32->tmExternalLeading = ptm16->tmExternalLeading;
266     ptm32->tmAveCharWidth = ptm16->tmAveCharWidth;
267     ptm32->tmMaxCharWidth = ptm16->tmMaxCharWidth;
268     ptm32->tmWeight = ptm16->tmWeight;
269     ptm32->tmOverhang = ptm16->tmOverhang;
270     ptm32->tmDigitizedAspectX = ptm16->tmDigitizedAspectX;
271     ptm32->tmDigitizedAspectY = ptm16->tmDigitizedAspectY;
272     ptm32->tmFirstChar = ptm16->tmFirstChar;
273     ptm32->tmLastChar = ptm16->tmLastChar;
274     ptm32->tmDefaultChar = ptm16->tmDefaultChar;
275     ptm32->tmBreakChar = ptm16->tmBreakChar;
276     ptm32->tmItalic = ptm16->tmItalic;
277     ptm32->tmUnderlined = ptm16->tmUnderlined;
278     ptm32->tmStruckOut = ptm16->tmStruckOut;
279     ptm32->tmPitchAndFamily = ptm16->tmPitchAndFamily;
280     ptm32->tmCharSet = ptm16->tmCharSet;
281 }
282
283 void FONT_TextMetric32Ato32W(const LPTEXTMETRICA ptm32A, LPTEXTMETRICW ptm32W )
284 {
285     ptm32W->tmHeight = ptm32A->tmHeight;
286     ptm32W->tmAscent = ptm32A->tmAscent;
287     ptm32W->tmDescent = ptm32A->tmDescent;
288     ptm32W->tmInternalLeading = ptm32A->tmInternalLeading;
289     ptm32W->tmExternalLeading = ptm32A->tmExternalLeading;
290     ptm32W->tmAveCharWidth = ptm32A->tmAveCharWidth;
291     ptm32W->tmMaxCharWidth = ptm32A->tmMaxCharWidth;
292     ptm32W->tmWeight = ptm32A->tmWeight;
293     ptm32W->tmOverhang = ptm32A->tmOverhang;
294     ptm32W->tmDigitizedAspectX = ptm32A->tmDigitizedAspectX;
295     ptm32W->tmDigitizedAspectY = ptm32A->tmDigitizedAspectY;
296     ptm32W->tmFirstChar = ptm32A->tmFirstChar;
297     ptm32W->tmLastChar = ptm32A->tmLastChar;
298     ptm32W->tmDefaultChar = ptm32A->tmDefaultChar;
299     ptm32W->tmBreakChar = ptm32A->tmBreakChar;
300     ptm32W->tmItalic = ptm32A->tmItalic;
301     ptm32W->tmUnderlined = ptm32A->tmUnderlined;
302     ptm32W->tmStruckOut = ptm32A->tmStruckOut;
303     ptm32W->tmPitchAndFamily = ptm32A->tmPitchAndFamily;
304     ptm32W->tmCharSet = ptm32A->tmCharSet;
305 }
306
307 /***********************************************************************
308  *           CreateFontIndirect16   (GDI.57)
309  */
310 HFONT16 WINAPI CreateFontIndirect16( const LOGFONT16 *font )
311 {
312     HFONT16 hFont = 0;
313
314     if (font)
315     {
316         hFont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
317         if( hFont )
318         {
319             FONTOBJ* fontPtr;
320             fontPtr = (FONTOBJ *) GDI_HEAP_LOCK( hFont );
321             memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
322
323             TRACE("(%i %i %i %i) '%s' %s %s => %04x\n",
324                   font->lfHeight, font->lfWidth, 
325                   font->lfEscapement, font->lfOrientation,
326                   font->lfFaceName ? font->lfFaceName : "NULL",
327                   font->lfWeight > 400 ? "Bold" : "",
328                   font->lfItalic ? "Italic" : "", hFont);
329
330             if (font->lfEscapement != font->lfOrientation) {
331               /* this should really depend on whether GM_ADVANCED is set */
332               fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
333               WARN("orientation angle %f set to "
334                    "escapement angle %f for new font %04x\n", 
335                    font->lfOrientation/10., font->lfEscapement/10., hFont);
336             }
337             GDI_HEAP_UNLOCK( hFont );
338         }
339     }
340     else WARN("(NULL) => NULL\n");
341
342     return hFont;
343 }
344
345 /***********************************************************************
346  *           CreateFontIndirectA   (GDI32.44)
347  */
348 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *font )
349 {
350     LOGFONT16 font16;
351
352     FONT_LogFont32ATo16( font, &font16 );
353     return CreateFontIndirect16( &font16 );
354 }
355
356 /***********************************************************************
357  *           CreateFontIndirectW   (GDI32.45)
358  */
359 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *font )
360 {
361     LOGFONT16 font16;
362
363     FONT_LogFont32WTo16( font, &font16 );
364     return CreateFontIndirect16( &font16 );
365 }
366
367 /***********************************************************************
368  *           CreateFont16    (GDI.56)
369  */
370 HFONT16 WINAPI CreateFont16(INT16 height, INT16 width, INT16 esc, INT16 orient,
371                             INT16 weight, BYTE italic, BYTE underline,
372                             BYTE strikeout, BYTE charset, BYTE outpres,
373                             BYTE clippres, BYTE quality, BYTE pitch,
374                             LPCSTR name )
375 {
376     LOGFONT16 logfont;
377
378     TRACE("('%s',%d,%d)\n", (name ? name : "(null)") , height, width);
379
380     logfont.lfHeight = height;
381     logfont.lfWidth = width;
382     logfont.lfEscapement = esc;
383     logfont.lfOrientation = orient;
384     logfont.lfWeight = weight;
385     logfont.lfItalic = italic;
386     logfont.lfUnderline = underline;
387     logfont.lfStrikeOut = strikeout;
388     logfont.lfCharSet = charset;
389     logfont.lfOutPrecision = outpres;
390     logfont.lfClipPrecision = clippres;
391     logfont.lfQuality = quality;
392     logfont.lfPitchAndFamily = pitch;
393    
394     if (name) 
395         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
396     else 
397         logfont.lfFaceName[0] = '\0';
398
399     return CreateFontIndirect16( &logfont );
400 }
401
402 /*************************************************************************
403  *           CreateFontA    (GDI32.43)
404  */
405 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
406                               INT orient, INT weight, DWORD italic,
407                               DWORD underline, DWORD strikeout, DWORD charset,
408                               DWORD outpres, DWORD clippres, DWORD quality,
409                               DWORD pitch, LPCSTR name )
410 {
411     return (HFONT)CreateFont16( height, width, esc, orient, weight, italic,
412                                   underline, strikeout, charset, outpres,
413                                   clippres, quality, pitch, name );
414 }
415
416 /*************************************************************************
417  *           CreateFontW    (GDI32.46)
418  */
419 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
420                               INT orient, INT weight, DWORD italic,
421                               DWORD underline, DWORD strikeout, DWORD charset,
422                               DWORD outpres, DWORD clippres, DWORD quality,
423                               DWORD pitch, LPCWSTR name )
424 {
425     LPSTR namea = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
426     HFONT ret = (HFONT)CreateFont16( height, width, esc, orient, weight,
427                                          italic, underline, strikeout, charset,
428                                          outpres, clippres, quality, pitch,
429                                          namea );
430     if (namea) HeapFree( GetProcessHeap(), 0, namea );
431     return ret;
432 }
433
434
435 /***********************************************************************
436  *           FONT_GetObject16
437  */
438 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
439 {
440     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
441     memcpy( buffer, &font->logfont, count );
442     return count;
443 }
444
445 /***********************************************************************
446  *           FONT_GetObjectA
447  */
448 INT FONT_GetObjectA( FONTOBJ *font, INT count, LPSTR buffer )
449 {
450     LOGFONTA fnt32;
451
452     FONT_LogFont16To32A( &font->logfont, &fnt32 );
453
454     if (count > sizeof(fnt32)) count = sizeof(fnt32);
455     memcpy( buffer, &fnt32, count );
456     return count;
457 }
458 /***********************************************************************
459  *           FONT_GetObjectW
460  */
461 INT FONT_GetObjectW( FONTOBJ *font, INT count, LPSTR buffer )
462 {
463     LOGFONTW fnt32;
464
465     FONT_LogFont16To32W( &font->logfont, &fnt32 );
466
467     if (count > sizeof(fnt32)) count = sizeof(fnt32);
468     memcpy( buffer, &fnt32, count );
469     return count;
470 }
471
472
473 /***********************************************************************
474  *              FONT_EnumInstance16
475  *
476  * Called by the device driver layer to pass font info
477  * down to the application.
478  */
479 static INT FONT_EnumInstance16( LPENUMLOGFONTEX16 plf, 
480                                   LPNEWTEXTMETRIC16 ptm, UINT16 fType, LPARAM lp )
481 {
482 #define pfe ((fontEnum16*)lp)
483     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || 
484         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
485     {
486         memcpy( pfe->lpLogFont, plf, sizeof(ENUMLOGFONT16) );
487         memcpy( pfe->lpTextMetric, ptm, sizeof(NEWTEXTMETRIC16) );
488
489         return pfe->lpEnumFunc( pfe->segLogFont, pfe->segTextMetric, fType, (LPARAM)(pfe->lpData) );
490     }
491 #undef pfe
492     return 1;
493 }
494
495 /***********************************************************************
496  *              FONT_EnumInstance
497  */
498 static INT FONT_EnumInstance( LPENUMLOGFONTEX16 plf,
499                                   LPNEWTEXTMETRIC16 ptm, UINT16 fType, LPARAM lp )
500 {
501     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
502
503 #define pfe ((fontEnum32*)lp)
504     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || 
505         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
506     {
507         /* convert font metrics */
508
509         if( pfe->dwFlags & ENUM_UNICODE )
510         {
511             FONT_EnumLogFontEx16To32W( plf, pfe->lpLogFont );
512             FONT_TextMetric16to32W( (LPTEXTMETRIC16)ptm, (LPTEXTMETRICW)(pfe->lpTextMetric) );
513         
514             return pfe->lpEnumFunc( pfe->lpLogFont, pfe->lpTextMetric, fType, pfe->lpData );
515         }
516         else
517         {
518             ENUMLOGFONTEXA logfont;
519
520             FONT_EnumLogFontEx16To32A( plf, &logfont);
521             FONT_TextMetric16to32A( (LPTEXTMETRIC16)ptm, (LPTEXTMETRICA)pfe->lpTextMetric );
522
523             return pfe->lpEnumFunc( (LPENUMLOGFONTEXW)&logfont, 
524                                 pfe->lpTextMetric, fType, pfe->lpData );
525         }
526     }
527 #undef pfe
528     return 1;
529 }
530
531 /***********************************************************************
532  *              EnumFontFamiliesEx16    (GDI.613)
533  */
534 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
535                                    FONTENUMPROCEX16 efproc, LPARAM lParam,
536                                    DWORD dwFlags)
537 {
538     INT16       retVal = 0;
539     DC*         dc = (DC*) GDI_GetObjPtr( hDC, DC_MAGIC );
540
541     if( dc && dc->funcs->pEnumDeviceFonts )
542     {
543         LPNEWTEXTMETRICEX16     lptm16 = SEGPTR_ALLOC( sizeof(NEWTEXTMETRICEX16) );
544         if( lptm16 )
545         {
546             LPENUMLOGFONTEX16   lplf16 = SEGPTR_ALLOC( sizeof(ENUMLOGFONTEX16) );
547             if( lplf16 )
548             {
549                 fontEnum16      fe16;
550
551                 fe16.lpLogFontParam = plf;
552                 fe16.lpEnumFunc = efproc;
553                 fe16.lpData = lParam;
554                 
555                 fe16.lpTextMetric = lptm16;
556                 fe16.lpLogFont = lplf16;
557                 fe16.segTextMetric = SEGPTR_GET(lptm16);
558                 fe16.segLogFont = SEGPTR_GET(lplf16);
559
560                 retVal = dc->funcs->pEnumDeviceFonts( dc, plf, FONT_EnumInstance16, (LPARAM)&fe16 );
561
562                 SEGPTR_FREE(lplf16);
563             }
564             SEGPTR_FREE(lptm16);
565         }
566     }
567     return retVal;
568 }
569
570 /***********************************************************************
571  *              FONT_EnumFontFamiliesEx
572  */
573 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCEXW efproc, 
574                                                    LPARAM lParam, DWORD dwUnicode)
575 {
576     DC*         dc = (DC*) GDI_GetObjPtr( hDC, DC_MAGIC );
577
578     if( dc && dc->funcs->pEnumDeviceFonts )
579     {
580         LOGFONT16               lf16;
581         NEWTEXTMETRICEXW        tm32w;
582         ENUMLOGFONTEXW  lf32w;
583         fontEnum32              fe32;
584
585         fe32.lpLogFontParam = plf;
586         fe32.lpEnumFunc = efproc;
587         fe32.lpData = lParam;
588         
589         fe32.lpTextMetric = &tm32w;
590         fe32.lpLogFont = &lf32w;
591         fe32.dwFlags = dwUnicode;
592
593         /* the only difference between LOGFONT32A and LOGFONT32W is in the lfFaceName */
594
595         if( plf->lfFaceName[0] )
596         {
597             if( dwUnicode )
598                 lstrcpynWtoA( lf16.lfFaceName, plf->lfFaceName, LF_FACESIZE );
599             else
600                 lstrcpynA( lf16.lfFaceName, (LPCSTR)plf->lfFaceName, LF_FACESIZE );
601         }
602         else lf16.lfFaceName[0] = '\0';
603         lf16.lfCharSet = plf->lfCharSet;
604
605         return dc->funcs->pEnumDeviceFonts( dc, &lf16, FONT_EnumInstance, (LPARAM)&fe32 );
606     }
607     return 0;
608 }
609
610 /***********************************************************************
611  *              EnumFontFamiliesExW     (GDI32.82)
612  */
613 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
614                                     FONTENUMPROCEXW efproc, 
615                                     LPARAM lParam, DWORD dwFlags )
616 {
617     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
618 }
619
620 /***********************************************************************
621  *              EnumFontFamiliesExA     (GDI32.81)
622  */
623 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
624                                     FONTENUMPROCEXA efproc, 
625                                     LPARAM lParam, DWORD dwFlags)
626 {
627     return  FONT_EnumFontFamiliesEx( hDC, (LPLOGFONTW)plf, 
628                                       (FONTENUMPROCEXW)efproc, lParam, 0);
629 }
630
631 /***********************************************************************
632  *              EnumFontFamilies16      (GDI.330)
633  */
634 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
635                                  FONTENUMPROC16 efproc, LPARAM lpData )
636 {
637     LOGFONT16   lf;
638
639     lf.lfCharSet = DEFAULT_CHARSET;
640     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
641     else lf.lfFaceName[0] = '\0';
642
643     return EnumFontFamiliesEx16( hDC, &lf, (FONTENUMPROCEX16)efproc, lpData, 0 );
644 }
645
646 /***********************************************************************
647  *              EnumFontFamiliesA       (GDI32.80)
648  */
649 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
650                                   FONTENUMPROCA efproc, LPARAM lpData )
651 {
652     LOGFONTA    lf;
653
654     lf.lfCharSet = DEFAULT_CHARSET;
655     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
656     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
657
658     return FONT_EnumFontFamiliesEx( hDC, (LPLOGFONTW)&lf, 
659                                            (FONTENUMPROCEXW)efproc, lpData, 0 );
660 }
661
662 /***********************************************************************
663  *              EnumFontFamiliesW       (GDI32.83)
664  */
665 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
666                                   FONTENUMPROCW efproc, LPARAM lpData )
667 {
668     LOGFONTW  lf;
669
670     lf.lfCharSet = DEFAULT_CHARSET;
671     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
672     else lf.lfFaceName[0] = 0;
673
674     return FONT_EnumFontFamiliesEx( hDC, &lf, (FONTENUMPROCEXW)efproc, 
675                                                 lpData, ENUM_UNICODE );
676 }
677
678 /***********************************************************************
679  *              EnumFonts16             (GDI.70)
680  */
681 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
682                           LPARAM lpData )
683 {
684     return EnumFontFamilies16( hDC, lpName, (FONTENUMPROCEX16)efproc, lpData );
685 }
686
687 /***********************************************************************
688  *              EnumFontsA              (GDI32.84)
689  */
690 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
691                            LPARAM lpData )
692 {
693     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
694 }
695
696 /***********************************************************************
697  *              EnumFontsW              (GDI32.85)
698  */
699 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
700                            LPARAM lpData )
701 {
702     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
703 }
704
705
706 /***********************************************************************
707  *           GetTextCharacterExtra16    (GDI.89)
708  */
709 INT16 WINAPI GetTextCharacterExtra16( HDC16 hdc )
710 {
711     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
712     if (!dc) return 0;
713     return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
714                  / dc->vportExtX );
715 }
716
717
718 /***********************************************************************
719  *           GetTextCharacterExtra    (GDI32.225)
720  */
721 INT WINAPI GetTextCharacterExtra( HDC hdc )
722 {
723     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
724     if (!dc) return 0;
725     return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
726                  / dc->vportExtX );
727 }
728
729
730 /***********************************************************************
731  *           SetTextCharacterExtra16    (GDI.8)
732  */
733 INT16 WINAPI SetTextCharacterExtra16( HDC16 hdc, INT16 extra )
734 {
735     return (INT16)SetTextCharacterExtra( hdc, extra );
736 }
737
738
739 /***********************************************************************
740  *           SetTextCharacterExtra    (GDI32.337)
741  */
742 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
743 {
744     INT prev;
745     DC * dc = DC_GetDCPtr( hdc );
746     if (!dc) return 0;
747     if (dc->funcs->pSetTextCharacterExtra)
748         return dc->funcs->pSetTextCharacterExtra( dc, extra );
749     extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;
750     prev = dc->w.charExtra;
751     dc->w.charExtra = abs(extra);
752     return (prev * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
753 }
754
755
756 /***********************************************************************
757  *           SetTextJustification16    (GDI.10)
758  */
759 INT16 WINAPI SetTextJustification16( HDC16 hdc, INT16 extra, INT16 breaks )
760 {
761     return SetTextJustification( hdc, extra, breaks );
762 }
763
764
765 /***********************************************************************
766  *           SetTextJustification    (GDI32.339)
767  */
768 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
769 {
770     DC * dc = DC_GetDCPtr( hdc );
771     if (!dc) return 0;
772     if (dc->funcs->pSetTextJustification)
773         return dc->funcs->pSetTextJustification( dc, extra, breaks );
774
775     extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
776     if (!extra) breaks = 0;
777     dc->w.breakTotalExtra = extra;
778     dc->w.breakCount = breaks;
779     if (breaks)
780     {
781         dc->w.breakExtra = extra / breaks;
782         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
783     }
784     else
785     {
786         dc->w.breakExtra = 0;
787         dc->w.breakRem   = 0;
788     }
789     return 1;
790 }
791
792
793 /***********************************************************************
794  *           GetTextFace16    (GDI.92)
795  */
796 INT16 WINAPI GetTextFace16( HDC16 hdc, INT16 count, LPSTR name )
797 {
798         return GetTextFaceA(hdc,count,name);
799 }
800
801 /***********************************************************************
802  *           GetTextFaceA    (GDI32.234)
803  */
804 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
805 {
806     FONTOBJ *font;
807
808     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
809     if (!dc) return 0;
810     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
811         return 0;
812     if (name) 
813         lstrcpynA( name, font->logfont.lfFaceName, count );
814     GDI_HEAP_UNLOCK( dc->w.hFont );
815     if (name)
816         return strlen(name);
817     else
818         return strlen(font->logfont.lfFaceName) + 1;
819 }
820
821 /***********************************************************************
822  *           GetTextFaceW    (GDI32.235)
823  */
824 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
825 {
826     LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, count );
827     INT res = GetTextFaceA(hdc,count,nameA);
828     lstrcpyAtoW( name, nameA );
829     HeapFree( GetProcessHeap(), 0, nameA );
830     return res;
831 }
832
833
834 /***********************************************************************
835  *           GetTextExtent16    (GDI.91)
836  */
837 DWORD WINAPI GetTextExtent16( HDC16 hdc, LPCSTR str, INT16 count )
838 {
839     SIZE16 size;
840     if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
841     return MAKELONG( size.cx, size.cy );
842 }
843
844
845 /***********************************************************************
846  *           GetTextExtentPoint16    (GDI.471)
847  *
848  * FIXME: Should this have a bug for compatibility?
849  * Original Windows versions of GetTextExtentPoint{A,W} have documented
850  * bugs (-> MSDN KB q147647.txt).
851  */
852 BOOL16 WINAPI GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count,
853                                     LPSIZE16 size )
854 {
855     SIZE size32;
856     BOOL ret;
857     TRACE("%04x, %p (%s), %d, %p\n", hdc, str, debugstr_an(str, count), count,
858           size);
859     ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
860     CONV_SIZE32TO16( &size32, size );
861     return (BOOL16)ret;
862 }
863
864
865 /***********************************************************************
866  *           GetTextExtentPoint32A    (GDI32.230)
867  */
868 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
869                                      LPSIZE size )
870 {
871     LPWSTR p;
872     BOOL ret;
873     UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
874     UINT wlen;
875
876   /* str may not be 0 terminated so we can't use HEAP_strdupWtoA.
877    * We allocate one more than we need so that lstrcpynWtoA can write a
878    * trailing 0 if it wants.
879    */
880
881     wlen = MultiByteToWideChar(codepage,0,str,count,NULL,0);
882     p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) );
883     wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen);
884
885     ret = GetTextExtentPoint32W( hdc, p, wlen, size );
886     HeapFree( GetProcessHeap(), 0, p );
887     return ret;
888 }
889
890
891 /***********************************************************************
892  * GetTextExtentPoint32W [GDI32.231]  Computes width/height for a string
893  *
894  * Computes width and height of the specified string.
895  *
896  * RETURNS
897  *    Success: TRUE
898  *    Failure: FALSE
899  */
900 BOOL WINAPI GetTextExtentPoint32W(
901     HDC hdc,     /* [in]  Handle of device context */
902     LPCWSTR str,   /* [in]  Address of text string */
903     INT count,   /* [in]  Number of characters in string */
904     LPSIZE size) /* [out] Address of structure for string size */
905 {
906     DC * dc = DC_GetDCPtr( hdc );
907     if (!dc || !dc->funcs->pGetTextExtentPoint ||
908         !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
909         return FALSE;
910
911     TRACE("(%08x %s %d %p): returning %d,%d\n",
912           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
913     return TRUE;
914 }
915
916
917 /***********************************************************************
918  *           GetTextExtentPointA    (GDI32.232)
919  */
920 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
921                                           LPSIZE size )
922 {
923     TRACE("not bug compatible.\n");
924     return GetTextExtentPoint32A( hdc, str, count, size );
925 }
926
927 /***********************************************************************
928  *           GetTextExtentPointW   (GDI32.233)
929  */
930 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
931                                           LPSIZE size )
932 {
933     TRACE("not bug compatible.\n");
934     return GetTextExtentPoint32W( hdc, str, count, size );
935 }
936
937
938 /***********************************************************************
939  *           GetTextExtentExPointA    (GDI32.228)
940  */
941 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
942                                    INT maxExt, LPINT lpnFit,
943                                    LPINT alpDx, LPSIZE size )
944 {
945     LPWSTR p;
946     BOOL ret;
947
948   /* Docs say str should be 0 terminated here, but we'll use count just in case
949    */ 
950
951     p = HeapAlloc( GetProcessHeap(), 0, (count+1) * sizeof(WCHAR) );
952     lstrcpynAtoW(p, str, count+1);
953     ret = GetTextExtentExPointW( hdc, p, count, maxExt, lpnFit, alpDx, size);
954     HeapFree( GetProcessHeap(), 0, p );
955     return ret;
956 }
957
958
959 /***********************************************************************
960  *           GetTextExtentExPointW    (GDI32.229)
961  */
962
963 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
964                                    INT maxExt, LPINT lpnFit,
965                                    LPINT alpDx, LPSIZE size )
966 {
967     int index, nFit, extent;
968     SIZE tSize;
969     DC * dc = DC_GetDCPtr( hdc );
970
971     if (!dc || !dc->funcs->pGetTextExtentPoint) return FALSE;
972
973     size->cx = size->cy = nFit = extent = 0;
974     for(index = 0; index < count; index++)
975     {
976         if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
977         if( extent+tSize.cx < maxExt )
978         {
979             extent+=tSize.cx;
980             nFit++;
981             str++;
982             if( alpDx ) alpDx[index] = extent;
983             if( tSize.cy > size->cy ) size->cy = tSize.cy;
984         }
985         else break;
986     }
987     size->cx = extent;
988     *lpnFit = nFit;
989
990     TRACE("(%08x %s %d) returning %d %d %d\n",
991           hdc,debugstr_wn(str,count),maxExt,nFit, size->cx,size->cy);
992     return TRUE;
993 }
994
995 /***********************************************************************
996  *           GetTextMetrics16    (GDI.93)
997  */
998 BOOL16 WINAPI GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
999 {
1000     TEXTMETRICA tm32;
1001
1002     if (!GetTextMetricsA( (HDC)hdc, &tm32 )) return FALSE;
1003     FONT_TextMetric32Ato16( &tm32, metrics );
1004     return TRUE;
1005 }
1006
1007
1008 /***********************************************************************
1009  *           GetTextMetricsA    (GDI32.236)
1010  */
1011 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1012 {
1013     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1014     if (!dc)
1015     {
1016         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
1017             return FALSE;
1018     }
1019
1020     if (!dc->funcs->pGetTextMetrics ||
1021         !dc->funcs->pGetTextMetrics( dc, metrics ))
1022         return FALSE;
1023
1024     /* device layer returns values in device units
1025      * therefore we have to convert them to logical */
1026
1027 #define WDPTOLP(x) ((x<0)?                                      \
1028                 (-abs((x)*dc->wndExtX/dc->vportExtX)):          \
1029                 (abs((x)*dc->wndExtX/dc->vportExtX)))
1030 #define HDPTOLP(y) ((y<0)?                                      \
1031                 (-abs((y)*dc->wndExtY/dc->vportExtY)):          \
1032                 (abs((y)*dc->wndExtY/dc->vportExtY)))
1033         
1034     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1035     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1036     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1037     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1038     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1039     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1040     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1041     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1042
1043     TRACE("text metrics:\n"
1044           "    Weight = %03li\t FirstChar = %03i\t AveCharWidth = %li\n"
1045           "    Italic = % 3i\t LastChar = %03i\t\t MaxCharWidth = %li\n"
1046           "    UnderLined = %01i\t DefaultChar = %03i\t Overhang = %li\n"
1047           "    StruckOut = %01i\t BreakChar = %03i\t CharSet = %i\n"
1048           "    PitchAndFamily = %02x\n"
1049           "    --------------------\n"
1050           "    InternalLeading = %li\n"
1051           "    Ascent = %li\n"
1052           "    Descent = %li\n"
1053           "    Height = %li\n",
1054           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1055           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1056           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1057           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1058           metrics->tmPitchAndFamily,
1059           metrics->tmInternalLeading,
1060           metrics->tmAscent,
1061           metrics->tmDescent,
1062           metrics->tmHeight );
1063     return TRUE;
1064 }
1065
1066
1067 /***********************************************************************
1068  *           GetTextMetricsW    (GDI32.237)
1069  */
1070 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1071 {
1072     TEXTMETRICA tm;
1073     if (!GetTextMetricsA( (HDC16)hdc, &tm )) return FALSE;
1074     FONT_TextMetric32Ato32W( &tm, metrics );
1075     return TRUE;
1076 }
1077
1078
1079 /***********************************************************************
1080  * GetOutlineTextMetrics16 [GDI.308]  Gets metrics for TrueType fonts.
1081  *
1082  * NOTES
1083  *    lpOTM should be LPOUTLINETEXTMETRIC
1084  *
1085  * RETURNS
1086  *    Success: Non-zero or size of required buffer
1087  *    Failure: 0
1088  */
1089 UINT16 WINAPI GetOutlineTextMetrics16(
1090     HDC16 hdc,    /* [in]  Handle of device context */
1091     UINT16 cbData, /* [in]  Size of metric data array */
1092     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1093 {
1094     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1095     return 0;
1096 }
1097
1098
1099 /***********************************************************************
1100  * GetOutlineTextMetricsA [GDI.207]  Gets metrics for TrueType fonts.
1101  *
1102  *
1103  * RETURNS
1104  *    Success: Non-zero or size of required buffer
1105  *    Failure: 0
1106  */
1107 UINT WINAPI GetOutlineTextMetricsA(
1108     HDC hdc,    /* [in]  Handle of device context */
1109     UINT cbData, /* [in]  Size of metric data array */
1110     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1111 {
1112
1113
1114     UINT rtn = FALSE;
1115     LPTEXTMETRICA lptxtMetr;
1116
1117
1118
1119     if (lpOTM == 0)
1120     {
1121         
1122         lpOTM = (LPOUTLINETEXTMETRICA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OUTLINETEXTMETRICA));
1123         rtn = sizeof(OUTLINETEXTMETRICA);
1124         cbData = rtn;
1125     } else
1126     {
1127         cbData = sizeof(*lpOTM);
1128         rtn = cbData;
1129     };
1130
1131     lpOTM->otmSize = cbData;
1132
1133     lptxtMetr =HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TEXTMETRICA));
1134     
1135     if (!GetTextMetricsA(hdc,lptxtMetr))
1136     {
1137         return 0;
1138     } else
1139     {
1140        memcpy(&(lpOTM->otmTextMetrics),lptxtMetr,sizeof(TEXTMETRICA));
1141     };
1142
1143     HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,lptxtMetr);
1144     
1145     lpOTM->otmFilter = 0;
1146
1147     lpOTM->otmPanoseNumber.bFamilyType  = 0;
1148     lpOTM->otmPanoseNumber.bSerifStyle  = 0;
1149     lpOTM->otmPanoseNumber.bWeight      = 0;
1150     lpOTM->otmPanoseNumber.bProportion  = 0;
1151     lpOTM->otmPanoseNumber.bContrast    = 0;
1152     lpOTM->otmPanoseNumber.bStrokeVariation = 0;
1153     lpOTM->otmPanoseNumber.bArmStyle    = 0;
1154     lpOTM->otmPanoseNumber.bLetterform  = 0;
1155     lpOTM->otmPanoseNumber.bMidline     = 0;
1156     lpOTM->otmPanoseNumber.bXHeight     = 0;
1157
1158     lpOTM->otmfsSelection     = 0;
1159     lpOTM->otmfsType          = 0;
1160
1161     /*
1162      Further fill of the structure not implemented,
1163      Needs real values for the structure members
1164      */
1165     
1166     return rtn;
1167 }
1168
1169 /***********************************************************************
1170  *           GetOutlineTextMetricsW [GDI32.208]
1171  */
1172 UINT WINAPI GetOutlineTextMetricsW(
1173     HDC hdc,    /* [in]  Handle of device context */
1174     UINT cbData, /* [in]  Size of metric data array */
1175     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1176 {
1177     FIXME("(%d,%d,%p): stub\n", hdc, cbData, lpOTM);
1178     return 0; 
1179 }
1180
1181 /***********************************************************************
1182  *           GetCharWidth16    (GDI.350)
1183  */
1184 BOOL16 WINAPI GetCharWidth16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1185                               LPINT16 buffer )
1186 {
1187     BOOL        retVal = FALSE;
1188
1189     if( firstChar != lastChar )
1190     {
1191         LPINT   buf32 = (LPINT)HeapAlloc(GetProcessHeap(), 0,
1192                                  sizeof(INT)*(1 + (lastChar - firstChar)));
1193         if( buf32 )
1194         {
1195             LPINT       obuf32 = buf32;
1196             int         i;
1197
1198             retVal = GetCharWidth32A(hdc, firstChar, lastChar, buf32);
1199             if (retVal)
1200             {
1201                 for (i = firstChar; i <= lastChar; i++)
1202                     *buffer++ = *buf32++;
1203             }
1204             HeapFree(GetProcessHeap(), 0, obuf32);
1205         }
1206     }
1207     else /* happens quite often to warrant a special treatment */
1208     {
1209         INT chWidth;
1210         retVal = GetCharWidth32A(hdc, firstChar, lastChar, &chWidth );
1211        *buffer = chWidth;
1212     }
1213     return retVal;
1214 }
1215
1216
1217 /***********************************************************************
1218  *           GetCharWidth32A    (GDI32.155)
1219  */
1220 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1221                                LPINT buffer )
1222 {
1223     UINT i, extra;
1224     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1225     if (!dc)
1226     {
1227         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
1228             return FALSE;
1229     }
1230
1231     if (!dc->funcs->pGetCharWidth ||
1232         !dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer))
1233         return FALSE;
1234
1235     /* convert device units to logical */
1236
1237     extra = dc->vportExtX >> 1;
1238     for( i = firstChar; i <= lastChar; i++, buffer++ )
1239          *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
1240
1241     return TRUE;
1242 }
1243
1244
1245 /***********************************************************************
1246  *           GetCharWidth32W    (GDI32.158)
1247  */
1248 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1249                                LPINT buffer )
1250 {
1251     return GetCharWidth32A( hdc, firstChar, lastChar, buffer );
1252 }
1253
1254
1255 /* FIXME: all following APIs ******************************************/
1256  
1257
1258 /***********************************************************************
1259  *           SetMapperFlags16    (GDI.349)
1260  */
1261 DWORD WINAPI SetMapperFlags16( HDC16 hDC, DWORD dwFlag )
1262 {
1263     return SetMapperFlags( hDC, dwFlag );
1264 }
1265
1266
1267 /***********************************************************************
1268  *           SetMapperFlags    (GDI32.322)
1269  */
1270 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1271 {
1272     DC *dc = DC_GetDCPtr( hDC );
1273     DWORD ret = 0; 
1274     if(!dc) return 0;
1275     if(dc->funcs->pSetMapperFlags)
1276         ret = dc->funcs->pSetMapperFlags( dc, dwFlag );
1277     else
1278         FIXME("(0x%04x, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1279     GDI_HEAP_UNLOCK( hDC );
1280     return ret;
1281 }
1282
1283 /***********************************************************************
1284  *          GetAspectRatioFilterEx16  (GDI.486)
1285  */
1286 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1287 {
1288   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1289   return FALSE;
1290 }
1291
1292 /***********************************************************************
1293  *          GetAspectRatioFilterEx  (GDI32.142)
1294  */
1295 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1296 {
1297   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1298   return FALSE;
1299 }
1300
1301 /***********************************************************************
1302  *           GetCharABCWidths16   (GDI.307)
1303  */
1304 BOOL16 WINAPI GetCharABCWidths16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1305                                   LPABC16 abc )
1306 {
1307     ABC abc32;
1308     if (!GetCharABCWidthsA( hdc, firstChar, lastChar, &abc32 )) return FALSE;
1309     abc->abcA = abc32.abcA;
1310     abc->abcB = abc32.abcB;
1311     abc->abcC = abc32.abcC;
1312     return TRUE;
1313 }
1314
1315
1316 /***********************************************************************
1317  *           GetCharABCWidthsA   (GDI32.149)
1318  */
1319 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1320                                   LPABC abc )
1321 {
1322     return GetCharABCWidthsW( hdc, firstChar, lastChar, abc );
1323 }
1324
1325
1326 /******************************************************************************
1327  * GetCharABCWidthsW [GDI32.152]  Retrieves widths of characters in range
1328  *
1329  * PARAMS
1330  *    hdc       [I] Handle of device context
1331  *    firstChar [I] First character in range to query
1332  *    lastChar  [I] Last character in range to query
1333  *    abc       [O] Address of character-width structure
1334  *
1335  * NOTES
1336  *    Only works with TrueType fonts
1337  *
1338  * RETURNS
1339  *    Success: TRUE
1340  *    Failure: FALSE
1341  */
1342 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1343                                    LPABC abc )
1344 {
1345     /* No TrueType fonts in Wine so far */
1346     FIXME("(%04x,%04x,%04x,%p): stub\n", hdc, firstChar, lastChar, abc);
1347     return FALSE;
1348 }
1349
1350
1351 /***********************************************************************
1352  *           GetGlyphOutline16    (GDI.309)
1353  */
1354 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1355                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1356                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1357 {
1358     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1359           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1360     return (DWORD)-1; /* failure */
1361 }
1362
1363
1364 /***********************************************************************
1365  *           GetGlyphOutlineA    (GDI32.186)
1366  */
1367 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1368                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1369                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1370 {
1371     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1372           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1373     return (DWORD)-1; /* failure */
1374 }
1375
1376 /***********************************************************************
1377  *           GetGlyphOutlineW    (GDI32.187)
1378  */
1379 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1380                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1381                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1382 {
1383     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1384           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1385     return (DWORD)-1; /* failure */
1386 }
1387
1388 /***********************************************************************
1389  *           CreateScalableFontResource16   (GDI.310)
1390  */
1391 BOOL16 WINAPI CreateScalableFontResource16( UINT16 fHidden,
1392                                             LPCSTR lpszResourceFile,
1393                                             LPCSTR fontFile, LPCSTR path )
1394 {
1395     return CreateScalableFontResourceA( fHidden, lpszResourceFile,
1396                                           fontFile, path );
1397 }
1398
1399 /***********************************************************************
1400  *           CreateScalableFontResourceA   (GDI32.62)
1401  */
1402 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1403                                              LPCSTR lpszResourceFile,
1404                                              LPCSTR lpszFontFile,
1405                                              LPCSTR lpszCurrentPath )
1406 {
1407     /* fHidden=1 - only visible for the calling app, read-only, not
1408      * enumbered with EnumFonts/EnumFontFamilies
1409      * lpszCurrentPath can be NULL
1410      */
1411     FIXME("(%ld,%s,%s,%s): stub\n",
1412           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1413     return FALSE; /* create failed */
1414 }
1415
1416 /***********************************************************************
1417  *           CreateScalableFontResourceW   (GDI32.63)
1418  */
1419 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1420                                              LPCWSTR lpszResourceFile,
1421                                              LPCWSTR lpszFontFile,
1422                                              LPCWSTR lpszCurrentPath )
1423 {
1424     FIXME("(%ld,%p,%p,%p): stub\n",
1425           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1426     return FALSE; /* create failed */
1427 }
1428
1429
1430 /*************************************************************************
1431  *             GetRasterizerCaps16   (GDI.313)
1432  */
1433 BOOL16 WINAPI GetRasterizerCaps16( LPRASTERIZER_STATUS lprs, UINT16 cbNumBytes)
1434 {
1435     return GetRasterizerCaps( lprs, cbNumBytes );
1436 }
1437
1438
1439 /*************************************************************************
1440  *             GetRasterizerCaps   (GDI32.216)
1441  */
1442 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1443 {
1444   lprs->nSize = sizeof(RASTERIZER_STATUS);
1445   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1446   lprs->nLanguageID = 0;
1447   return TRUE;
1448 }
1449
1450
1451 /*************************************************************************
1452  *             GetKerningPairs16   (GDI.332)
1453  */
1454 INT16 WINAPI GetKerningPairs16( HDC16 hDC, INT16 cPairs,
1455                                 LPKERNINGPAIR16 lpKerningPairs )
1456 {
1457     /* At this time kerning is ignored (set to 0) */
1458     int i;
1459     FIXME("(%x,%d,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1460     for (i = 0; i < cPairs; i++) 
1461         lpKerningPairs[i].iKernAmount = 0;
1462     return 0;
1463 }
1464
1465
1466
1467 /*************************************************************************
1468  *             GetKerningPairsA   (GDI32.192)
1469  */
1470 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1471                                  LPKERNINGPAIR lpKerningPairs )
1472 {
1473     int i;
1474     FIXME("(%x,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1475     for (i = 0; i < cPairs; i++) 
1476         lpKerningPairs[i].iKernAmount = 0;
1477     return 0;
1478 }
1479
1480
1481 /*************************************************************************
1482  *             GetKerningPairsW   (GDI32.193)
1483  */
1484 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1485                                  LPKERNINGPAIR lpKerningPairs )
1486 {
1487     return GetKerningPairsA( hDC, cPairs, lpKerningPairs );
1488 }
1489
1490 /*************************************************************************
1491  * TranslateCharsetInfo [GDI32.382]
1492  *
1493  * Fills a CHARSETINFO structure for a character set, code page, or
1494  * font. This allows making the correspondance between different labelings
1495  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges) 
1496  * of the same encoding.
1497  *
1498  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1499  * only one codepage should be set in *lpSrc.
1500  *
1501  * RETURNS
1502  *   TRUE on success, FALSE on failure.
1503  *
1504  */
1505 BOOL WINAPI TranslateCharsetInfo(
1506   LPDWORD lpSrc, /*
1507        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1508        if flags == TCI_SRCCHARSET: a character set value
1509        if flags == TCI_SRCCODEPAGE: a code page value
1510                  */
1511   LPCHARSETINFO lpCs, /* structure to receive charset information */
1512   DWORD flags /* determines interpretation of lpSrc */
1513 ) {
1514     int index = 0;
1515     switch (flags) {
1516     case TCI_SRCFONTSIG:
1517         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1518       break;
1519     case TCI_SRCCODEPAGE:
1520       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1521       break;
1522     case TCI_SRCCHARSET:
1523       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1524       break;
1525     default:
1526       return FALSE;
1527     }
1528     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1529     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1530     return TRUE;
1531 }
1532
1533 /*************************************************************************
1534  *             GetFontLanguageInfo   (GDI32.182)
1535  */
1536 DWORD WINAPI GetFontLanguageInfo(HDC hdc) {
1537         /* return value 0 is correct for most cases anyway */
1538         FIXME("(%x):stub!\n", hdc);
1539         return 0;
1540 }
1541
1542 /*************************************************************************
1543  *             GetFontLanguageInfo   (GDI.616)
1544  */
1545 DWORD WINAPI GetFontLanguageInfo16(HDC16 hdc) {
1546         /* return value 0 is correct for most cases anyway */
1547         FIXME("(%x):stub!\n",hdc);
1548         return 0;
1549 }
1550
1551 /*************************************************************************
1552  * GetFontData [GDI32.181] Retrieve data for TrueType font
1553  *
1554  * RETURNS
1555  *
1556  * success: Number of bytes returned 
1557  * failure: GDI_ERROR
1558  *
1559  * NOTES
1560  *
1561  * Calls SetLastError()  
1562  *
1563  * BUGS
1564  *
1565  * Unimplemented
1566  */
1567 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset, 
1568     LPVOID buffer, DWORD length)
1569 {
1570     FIXME("(%x,%ld,%ld,%p,%ld): stub\n", hdc, table, offset, buffer, length);
1571     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1572     return GDI_ERROR;
1573 }
1574
1575 /*************************************************************************
1576  * GetFontData16 [GDI.311]
1577  *
1578  */
1579 DWORD WINAPI GetFontData16(HDC16 hdc, DWORD dwTable, DWORD dwOffset,
1580                             LPVOID lpvBuffer, DWORD cbData)
1581 {
1582     return GetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData);
1583 }
1584
1585 /*************************************************************************
1586  * GetCharacterPlacementA [GDI32.160]
1587  *
1588  * NOTES:
1589  *  the web browser control of ie4 calls this with dwFlags=0
1590  */
1591 DWORD WINAPI
1592 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1593                          INT nMaxExtent, GCP_RESULTSA *lpResults,
1594                          DWORD dwFlags)
1595 {
1596     DWORD ret=0;
1597     SIZE size;
1598
1599     TRACE("%s 0x%08x 0x%08x 0x%08lx:stub!\n",
1600           debugstr_a(lpString), uCount, nMaxExtent, dwFlags);
1601
1602     TRACE("lpOrder=%p lpDx=%p lpCaretPos=%p lpClass=%p "
1603           "lpOutString=%p lpGlyphs=%p\n",
1604           lpResults->lpOrder, lpResults->lpDx, lpResults->lpCaretPos,
1605           lpResults->lpClass, lpResults->lpOutString, lpResults->lpGlyphs);
1606
1607     if(dwFlags)                 FIXME("flags 0x%08lx ignored\n", dwFlags);
1608     if(lpResults->lpOrder)      FIXME("reordering not implemented\n");
1609     if(lpResults->lpCaretPos)   FIXME("caret positions not implemented\n");
1610     if(lpResults->lpClass)      FIXME("classes not implemented\n");
1611     if(lpResults->lpGlyphs)     FIXME("glyphs not implemented\n");
1612
1613     /* copy will do if the GCP_REORDER flag is not set */
1614     if(lpResults->lpOutString)
1615     {
1616       lstrcpynA(lpResults->lpOutString, lpString, uCount);
1617     }
1618
1619     if (lpResults->lpDx)
1620     {
1621       int i, c;
1622       for (i=0; i<uCount;i++)
1623       { 
1624         if (GetCharWidth32A(hdc, lpString[i], lpString[i], &c))
1625           lpResults->lpDx[i]= c;
1626       }
1627     }
1628
1629     if (GetTextExtentPoint32A(hdc, lpString, uCount, &size))
1630       ret = MAKELONG(size.cx, size.cy);
1631
1632     return ret;
1633 }
1634
1635 /*************************************************************************
1636  * GetCharacterPlacementW [GDI32.161]
1637  */
1638 DWORD WINAPI
1639 GetCharacterPlacementW(HDC hdc, LPCWSTR lpString, INT uCount,
1640                          INT nMaxExtent, GCP_RESULTSW *lpResults,
1641                          DWORD dwFlags)
1642 {
1643     /* return value 0 is correct for most cases anyway */
1644     FIXME(":stub!\n");
1645     return 0;
1646 }
1647
1648 /*************************************************************************
1649  *      GetCharABCWidthsFloatA [GDI32.150]
1650  */
1651 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
1652                                         LPABCFLOAT lpABCF)
1653 {
1654        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
1655        return 0;
1656 }
1657
1658 /*************************************************************************
1659  *      GetCharABCWidthsFloatW [GDI32.151]
1660  */
1661 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
1662                                         UINT iLastChar, LPABCFLOAT lpABCF)
1663 {
1664        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
1665        return 0;
1666 }
1667
1668 /*************************************************************************
1669  *      GetCharWidthFloatA [GDI32.156]
1670  */
1671 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
1672                                     UINT iLastChar, PFLOAT pxBuffer)
1673 {
1674        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
1675        return 0;
1676 }
1677
1678 /*************************************************************************
1679  *      GetCharWidthFloatW [GDI32.157]
1680  */
1681 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
1682                                     UINT iLastChar, PFLOAT pxBuffer)
1683 {
1684        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
1685        return 0;
1686 }
1687  
1688
1689 /***********************************************************************
1690  *                                                                     *
1691  *           Font Resource API                                         *
1692  *                                                                     *
1693  ***********************************************************************/
1694 /***********************************************************************
1695  *           AddFontResource16    (GDI.119)
1696  *
1697  *  Can be either .FON, or .FNT, or .TTF, or .FOT font file.
1698  *
1699  *  FIXME: Load header and find the best-matching font in the fontList;
1700  *         fixup dfPoints if all metrics are identical, otherwise create
1701  *         new fontAlias. When soft font support is ready this will
1702  *         simply create a new fontResource ('filename' will go into
1703  *         the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE 
1704  *         flag set. 
1705  */
1706 INT16 WINAPI AddFontResource16( LPCSTR filename )
1707 {
1708     return AddFontResourceA( filename );
1709 }
1710
1711
1712 /***********************************************************************
1713  *           AddFontResourceA    (GDI32.2)
1714  */
1715 INT WINAPI AddFontResourceA( LPCSTR str )
1716 {
1717     FIXME("(%s): stub! Read \"documentation/fonts\" how to install "
1718             "this font manually.\n", debugres_a(str));
1719     return 1;
1720 }
1721
1722
1723 /***********************************************************************
1724  *           AddFontResourceW    (GDI32.4)
1725  */
1726 INT WINAPI AddFontResourceW( LPCWSTR str )
1727 {
1728     FIXME("(%s): stub! Read \"documentation/fonts\" how to install "
1729             "this font manually.\n", debugres_w(str));
1730     return 1;
1731 }
1732
1733 /***********************************************************************
1734  *           RemoveFontResource16    (GDI.136)
1735  */
1736 BOOL16 WINAPI RemoveFontResource16( SEGPTR str )
1737 {
1738     FIXME("(%s): stub\n",       debugres_a(PTR_SEG_TO_LIN(str)));
1739     return TRUE;
1740 }
1741
1742
1743 /***********************************************************************
1744  *           RemoveFontResourceA    (GDI32.284)
1745  */
1746 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
1747 {
1748 /*  This is how it should look like */
1749 /*
1750     fontResource** ppfr;
1751     BOOL32 retVal = FALSE;
1752
1753     EnterCriticalSection( &crtsc_fonts_X11 );
1754     for( ppfr = &fontList; *ppfr; ppfr = &(*ppfr)->next )
1755          if( !strcasecmp( (*ppfr)->lfFaceName, str ) )
1756          {
1757              if(((*ppfr)->fr_flags & (FR_SOFTFONT | FR_SOFTRESOURCE)) &&
1758                  (*ppfr)->hOwnerProcess == GetCurrentProcess() )
1759              {
1760                  if( (*ppfr)->fo_count )
1761                      (*ppfr)->fr_flags |= FR_REMOVED;
1762                  else
1763                      XFONT_RemoveFontResource( ppfr );
1764              }
1765              retVal = TRUE;
1766          }
1767     LeaveCriticalSection( &crtsc_fonts_X11 );
1768     return retVal;
1769  */
1770     FIXME("(%s): stub\n", debugres_a(str));
1771     return TRUE;
1772 }
1773
1774
1775 /***********************************************************************
1776  *           RemoveFontResourceW    (GDI32.286)
1777  */
1778 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
1779 {
1780     FIXME("(%s): stub\n", debugres_w(str) );
1781     return TRUE;
1782 }