Release 960805
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * Enhacements by Juergen Marquardt 1996
7  *
8  * Implementation of a second font cache which 
9  * will be updated dynamically
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <X11/Xatom.h>
16 #include "font.h"
17 #include "metafile.h"
18 #include "options.h"
19 #include "string32.h"
20 #include "xmalloc.h"
21 #include "stddebug.h"
22 #include "debug.h"
23
24 #define FONTCACHE       32      /* dynamic font cache size */
25 #define MAX_FONTS       256
26 static LPLOGFONT16 lpLogFontList[MAX_FONTS+1];
27
28 static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
29
30 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
31                              (((cs)->rbearing|(cs)->lbearing| \
32                                (cs)->ascent|(cs)->descent) == 0))
33
34 /* 
35  * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
36  * character.  If the character is in the column and exists, then return the
37  * appropriate metrics (note that fonts with common per-character metrics will
38  * return min_bounds).  If none of these hold true, try again with the default
39  * char.
40  */
41 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
42 { \
43     cs = def; \
44     if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
45         if (fs->per_char == NULL) { \
46             cs = &fs->min_bounds; \
47         } else { \
48             cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
49             if (CI_NONEXISTCHAR(cs)) cs = def; \
50         } \
51     } \
52 }
53
54 #define CI_GET_DEFAULT_INFO(fs,cs) \
55   CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
56
57 struct FontStructure {
58         char *window;
59         char *x11;
60 } FontNames[32];
61 int FontSize;
62
63
64 /***********************************************************************
65  *           FONT_Init
66  */
67 BOOL FONT_Init( void )
68 {
69   char  temp[1024];
70   LPSTR ptr;
71   int i;
72
73   if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
74   {
75     for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
76       if( strcmp( ptr, "default" ) )
77         FontNames[i++].window = xstrdup( ptr );
78     FontSize = i;
79
80     for( i = 1; i < FontSize; i++ )
81     {
82         PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
83                                   temp, sizeof(temp) );
84         FontNames[i].x11 = xstrdup( temp );
85     }
86     PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
87     FontNames[0].x11 = xstrdup( temp );
88
89   } else {
90     FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
91     FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
92     FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
93     FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
94     FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
95     FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
96     FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
97     FontSize = 7;
98   }
99   return TRUE;
100 }
101
102 /***********************************************************************
103  *           FONT_ChkX11Family
104  *
105  * returns a valid X11 equivalent if a Windows face name 
106  * is like a X11 family  - or NULL if translation is needed
107  */
108 static char *FONT_ChkX11Family(char *winFaceName )
109 {
110   static char x11fam[32+2];   /* will be returned */
111   int i;
112
113   for(i = 0; lpLogFontList[i] != NULL; i++)
114     if( !lstrcmpi32A(winFaceName, lpLogFontList[i]->lfFaceName) )
115     {
116         strcpy(x11fam,"*-");
117         return strcat(x11fam,winFaceName);
118     }    
119   return NULL;               /* a FONT_TranslateName() call is needed */
120 }
121
122
123
124 /***********************************************************************
125  *           FONT_TranslateName
126  *
127  * Translate a Windows face name to its X11 equivalent.
128  * This will probably have to be customizable.
129  */
130 static const char *FONT_TranslateName( char *winFaceName )
131 {
132   int i;
133
134   for (i = 1; i < FontSize; i ++)
135     if( !strcmp( winFaceName, FontNames[i].window ) ) {
136       dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
137       return FontNames[i].x11;
138     }
139   return FontNames[0].x11;
140 }
141
142
143 /***********************************************************************
144  *           FONT_MatchFont
145  *
146  * Find a X font matching the logical font.
147  */
148 static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc )
149 {
150     char pattern[100];
151     const char *family, *weight, *charset;
152     char **names;
153     char slant, oldspacing, spacing;
154     int width, height, oldheight, count;
155     XFontStruct * fontStruct;
156     
157     dprintf_font(stddeb,
158         "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
159         font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
160     weight = (font->lfWeight > 550) ? "bold" : "medium";
161     slant = font->lfItalic ? 'i' : 'r';
162     if (font->lfHeight == -1)
163         height = 0;
164     else
165         height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
166     if (height == 0) height = 120;  /* Default height = 12 */
167     else if (height < 0)
168     {
169         /* If height is negative, it means the height of the characters */
170         /* *without* the internal leading. So we adjust it a bit to     */
171         /* compensate. 5/4 seems to give good results for small fonts.  */
172         /* 
173          * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write 
174         height = 10 * (-height * 9 / 8);
175          * may be we have to use an non linear function
176         */
177         /* assume internal leading is 2 pixels. Else small fonts will become
178          * very small. */
179         height = (height-2) * -10; 
180     }
181     else height *= 10;
182     width  = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
183     if (width < 0) {
184         dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
185                       width, font->lfWidth );
186         width = -width;
187     }
188
189     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
190               (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
191     
192   
193     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
194     if (*font->lfFaceName) {
195         family = FONT_ChkX11Family(font->lfFaceName);
196         /*--do _not_ translate if lfFaceName is family from X11  A.K.*/
197         if (!family) 
198           family = FONT_TranslateName( font->lfFaceName );
199         /* FIX ME: I don't if that's correct but it works J.M. */
200         spacing = '*';
201         }
202     else switch(font->lfPitchAndFamily & 0xf0)
203     {
204     case FF_ROMAN:
205       family = FONT_TranslateName( "roman" );
206       break;
207     case FF_SWISS:
208       family = FONT_TranslateName( "swiss" );
209       break;
210     case FF_MODERN:
211       family = FONT_TranslateName( "modern" );
212       break;
213     case FF_SCRIPT:
214       family = FONT_TranslateName( "script" );
215       break;
216     case FF_DECORATIVE:
217       family = FONT_TranslateName( "decorative" );
218       break;
219     default:
220       family = "*-*";
221       break;
222     }
223     oldheight = height;
224     oldspacing = spacing;
225     while (TRUE) {
226             /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
227             if ( width == 0 )
228               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
229                       family, weight, slant, height, spacing, charset);
230             else
231               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
232                       family, weight, slant, height, spacing, width, charset);
233             dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
234             names = XListFonts( display, pattern, 1, &count );
235             if (count > 0) break;
236             if (spacing == 'm') /* try 'c' if no 'm' found */ {
237
238                 spacing = 'c';
239                 continue;
240             } else if (spacing == 'p') /* try '*' if no 'p' found */ {
241                 spacing = '*';
242                 continue;
243             }
244             spacing = oldspacing;
245             height -= 10;               
246             if (height < 10) {
247                 if (slant == 'i') {
248                     /* try oblique if no italic font */
249                     slant = 'o';
250                     height = oldheight;
251                     continue;
252                 }
253                 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
254                     /* If a fixed spacing font could not be found, ignore
255                      * the family */
256                     family = "*-*";
257                     height = oldheight;
258                     continue;
259                 }
260                 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
261                 return NULL;
262             }
263     }
264     dprintf_font(stddeb,"        Found '%s'\n", *names );
265     if (!*font->lfFaceName)
266       ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
267       /* we need a font name for function GetTextFace() even if there isn't one ;-) */  
268     AnsiUpper(font->lfFaceName);
269
270     fontStruct = XLoadQueryFont( display, *names );
271     XFreeFontNames( names );
272     return fontStruct;
273 }
274
275
276 /***********************************************************************
277  *           FONT_GetMetrics
278  */
279 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
280                       TEXTMETRIC16 * metrics )
281 {    
282     int average, i, count;
283     unsigned long prop;
284         
285     metrics->tmAscent  = xfont->ascent;
286     metrics->tmDescent = xfont->descent;
287     metrics->tmHeight  = xfont->ascent + xfont->descent;
288
289     metrics->tmInternalLeading  = 0;
290     if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
291         metrics->tmInternalLeading = xfont->ascent - (short)prop;
292     metrics->tmExternalLeading  = 0;
293     metrics->tmMaxCharWidth     = xfont->max_bounds.width;
294     metrics->tmWeight           = logfont->lfWeight;
295     metrics->tmItalic           = logfont->lfItalic;
296     metrics->tmUnderlined       = logfont->lfUnderline;
297     metrics->tmStruckOut        = logfont->lfStrikeOut;
298     metrics->tmFirstChar        = xfont->min_char_or_byte2;
299     metrics->tmLastChar         = xfont->max_char_or_byte2;
300     metrics->tmDefaultChar      = xfont->default_char;
301     metrics->tmBreakChar        = ' ';
302     metrics->tmCharSet          = logfont->lfCharSet;
303     metrics->tmOverhang         = 0;
304     metrics->tmDigitizedAspectX = 1;
305     metrics->tmDigitizedAspectY = 1;
306     metrics->tmPitchAndFamily   = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
307     if (logfont->lfPitchAndFamily & FIXED_PITCH) 
308         metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
309
310     if (!xfont->per_char) average = metrics->tmMaxCharWidth;
311     else
312     {
313         XCharStruct * charPtr = xfont->per_char;
314         average = count = 0;
315         for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
316         {
317             if (!CI_NONEXISTCHAR( charPtr ))
318             {
319                 average += charPtr->width;
320                 count++;
321             }
322             charPtr++;
323         }
324         if (count) average = (average + count/2) / count;
325     }
326     metrics->tmAveCharWidth = average;
327 }
328
329 /***********************************************************************
330  *           GetGlyphOutLine    (GDI.309)
331  */
332 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, 
333                       DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2) 
334 {
335     fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
336              hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
337     return (DWORD)-1; /* failure */
338 }
339
340
341 /***********************************************************************
342  *           CreateScalableFontResource    (GDI.310)
343  */
344 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
345                                  LPSTR lpszFontFile, LPSTR lpszCurrentPath )
346 {
347     /* fHidden=1 - only visible for the calling app, read-only, not
348      * enumbered with EnumFonts/EnumFontFamilies
349      * lpszCurrentPath can be NULL
350      */
351     fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
352             fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
353     return FALSE; /* create failed */
354 }
355
356
357 /***********************************************************************
358  *           CreateFontIndirect16   (GDI.57)
359  */
360 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
361 {
362     FONTOBJ * fontPtr;
363     HFONT16 hfont;
364
365     if (!font)
366     {
367         fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
368         return 0;
369     }
370     hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
371     if (!hfont) return 0;
372     fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
373     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
374     AnsiLower( fontPtr->logfont.lfFaceName );
375     dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
376         font, font->lfHeight, font->lfWidth, hfont);
377     return hfont;
378 }
379
380
381 /***********************************************************************
382  *           CreateFontIndirect32A   (GDI32.44)
383  */
384 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
385 {
386     LOGFONT16 font16;
387
388     font16.lfHeight         = (INT16)font->lfHeight;
389     font16.lfWidth          = (INT16)font->lfWidth;
390     font16.lfEscapement     = (INT16)font->lfEscapement;
391     font16.lfOrientation    = (INT16)font->lfOrientation;
392     font16.lfWeight         = (INT16)font->lfWeight;
393     font16.lfItalic         = font->lfItalic;
394     font16.lfUnderline      = font->lfUnderline;
395     font16.lfStrikeOut      = font->lfStrikeOut;
396     font16.lfCharSet        = font->lfCharSet;
397     font16.lfOutPrecision   = font->lfOutPrecision;
398     font16.lfClipPrecision  = font->lfClipPrecision;
399     font16.lfQuality        = font->lfQuality;
400     font16.lfPitchAndFamily = font->lfPitchAndFamily;
401     lstrcpyn32A( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
402     return CreateFontIndirect16( &font16 );
403 }
404
405
406 /***********************************************************************
407  *           CreateFontIndirect32W   (GDI32.45)
408  */
409 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
410 {
411     LOGFONT16 font16;
412
413     font16.lfHeight         = (INT16)font->lfHeight;
414     font16.lfWidth          = (INT16)font->lfWidth;
415     font16.lfEscapement     = (INT16)font->lfEscapement;
416     font16.lfOrientation    = (INT16)font->lfOrientation;
417     font16.lfWeight         = (INT16)font->lfWeight;
418     font16.lfItalic         = font->lfItalic;
419     font16.lfUnderline      = font->lfUnderline;
420     font16.lfStrikeOut      = font->lfStrikeOut;
421     font16.lfCharSet        = font->lfCharSet;
422     font16.lfOutPrecision   = font->lfOutPrecision;
423     font16.lfClipPrecision  = font->lfClipPrecision;
424     font16.lfQuality        = font->lfQuality;
425     font16.lfPitchAndFamily = font->lfPitchAndFamily;
426     lstrcpynWtoA( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
427     return CreateFontIndirect16( &font16 );
428 }
429
430
431 /***********************************************************************
432  *           CreateFont16    (GDI.56)
433  */
434 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
435                       INT16 weight, BYTE italic, BYTE underline,
436                       BYTE strikeout, BYTE charset, BYTE outpres,
437                       BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
438 {
439     LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
440                       strikeout, charset, outpres, clippres, quality, pitch, };
441     dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
442     if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
443     else logfont.lfFaceName[0] = '\0';
444     return CreateFontIndirect16( &logfont );
445 }
446
447
448
449 /*************************************************************************
450  *           CreateFont32A    (GDI32.43)
451  */
452 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
453                        INT32 weight, DWORD italic, DWORD underline,
454                        DWORD strikeout, DWORD charset, DWORD outpres,
455                        DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
456 {
457     return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
458                                   underline, strikeout, charset, outpres,
459                                   clippres, quality, pitch, name );
460 }
461
462
463 /*************************************************************************
464  *           CreateFont32W    (GDI32.46)
465  */
466 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
467                        INT32 weight, DWORD italic, DWORD underline,
468                        DWORD strikeout, DWORD charset, DWORD outpres,
469                        DWORD clippres, DWORD quality, DWORD pitch,
470                        LPCWSTR name )
471 {
472     LPSTR namea = name ? STRING32_DupUniToAnsi(name) : NULL;
473     HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
474                                          italic, underline, strikeout, charset,
475                                          outpres, clippres, quality, pitch,
476                                          namea );
477     free(namea);
478     return ret;
479 }
480
481
482 /***********************************************************************
483  *           FONT_GetObject
484  */
485 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
486 {
487     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
488     memcpy( buffer, &font->logfont, count );
489     return count;
490 }
491
492
493 /***********************************************************************
494  *           FONT_SelectObject
495  */
496 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
497 {
498     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
499
500     static struct {
501                 HFONT           id;
502                 LOGFONT16       logfont;
503                 int             access;
504                 int             used;
505                 X_PHYSFONT      cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
506     int         i;
507
508     X_PHYSFONT * stockPtr;
509     HFONT prevHandle = dc->w.hFont;
510     XFontStruct * fontStruct;
511     dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
512
513 #if 0 /* From the code in SelectObject, this can not happen */
514       /* Load font if necessary */
515     if (!font)
516     {
517         HFONT hnewfont;
518
519         hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
520                               FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
521                               DEFAULT_QUALITY, FF_DONTCARE, "*" );
522         font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
523     }
524 #endif
525
526     if (dc->header.wMagic == METAFILE_DC_MAGIC)
527       if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
528         return prevHandle;
529       else
530         return 0;
531
532     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
533         stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
534     else {
535         stockPtr = NULL;
536         /*
537          * Ok, It's not a stock font but 
538          * may be it's cached in dynamic cache
539          */
540         for(i=0; i<FONTCACHE; i++) /* search for same handle */
541              if (cacheFonts[i].id==hfont) { /* Got the handle */
542                 /*
543                  * Check if Handle matches the font 
544                  */
545                 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
546                         /* No: remove handle id from dynamic font cache */
547                         cacheFonts[i].access=0;
548                         cacheFonts[i].used=0;
549                         cacheFonts[i].id=0;
550                         /* may be there is an unused handle which contains the font */
551                         for(i=0; i<FONTCACHE; i++) {
552                                 if((cacheFonts[i].used == 0) &&
553                                   (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
554                                         /* got it load from cache and set new handle id */
555                                         stockPtr = &cacheFonts[i].cacheFont;
556                                         cacheFonts[i].access=1;
557                                         cacheFonts[i].used=1;
558                                         cacheFonts[i].id=hfont;
559                                         dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
560                                         break;
561                                         }
562                                 }
563         
564                         }
565                 else {
566                         /* Yes: load from dynamic font cache */
567                         stockPtr = &cacheFonts[i].cacheFont;
568                         cacheFonts[i].access++;
569                         cacheFonts[i].used++;
570                         }
571                 break;
572                 }
573         }
574     if (!stockPtr || !stockPtr->fstruct)
575     {
576         if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
577         {
578               /* If it is not a stock font, we can simply return 0 */
579             if (!stockPtr) return 0;
580               /* Otherwise we must try to find a substitute */
581             dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
582             font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
583             font->logfont.lfPitchAndFamily |= FIXED_PITCH;
584             fontStruct = XLoadQueryFont( display, "fixed" );
585             if (!fontStruct)
586             {
587                 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
588                 exit( 1 );
589             }
590         }
591     }
592     else
593     {
594         fontStruct = stockPtr->fstruct;
595         dprintf_font(stddeb,
596                      "FONT_SelectObject: Loaded font from cache %04x %p\n",
597                      hfont, fontStruct );
598     }   
599
600       /* Unuse previous font */
601         for (i=0; i < FONTCACHE; i++) {
602                 if (cacheFonts[i].id == prevHandle) {
603                         if(cacheFonts[i].used == 0)
604                                 fprintf(stderr, "Trying to decrement a use count of 0.\n");
605                         else 
606                                 cacheFonts[i].used--;
607                 }
608         }
609
610       /* Store font */
611     dc->w.hFont = hfont;
612     if (stockPtr)
613     {
614         if (!stockPtr->fstruct)
615         {
616             stockPtr->fstruct = fontStruct;
617             FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
618         }
619         memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
620     }
621     else
622     {
623         /* 
624          * Check in cacheFont
625          */
626         cacheFontsMin=NULL;
627         for (i=0; i < FONTCACHE; i++) {
628                 if (cacheFonts[i].used==0) 
629                         if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
630                                 cacheFontsMin=&cacheFonts[i];
631                 }
632         if (!cacheFontsMin) {
633                 fprintf(stderr,"No unused font cache entry !!!!\n" );
634                 return prevHandle;
635         }
636         if (cacheFontsMin->id!=0) {
637                 dprintf_font(stddeb,
638                         "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
639                 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
640                 }
641         cacheFontsMin->cacheFont.fstruct = fontStruct;
642         FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
643         cacheFontsMin->access=1;
644         cacheFontsMin->used=1;
645         cacheFontsMin->id=hfont;
646         memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
647         memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
648
649     }
650     return prevHandle;
651 }
652
653
654 /***********************************************************************
655  *           GetTextCharacterExtra    (GDI.89)
656  */
657 short GetTextCharacterExtra( HDC hdc )
658 {
659     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
660     if (!dc) return 0;
661     return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
662                  / dc->w.VportExtX );
663 }
664
665
666 /***********************************************************************
667  *           SetTextCharacterExtra    (GDI.8)
668  */
669 short SetTextCharacterExtra( HDC hdc, short extra )
670 {
671     short prev;
672     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
673     if (!dc) return 0;
674     extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;    
675     prev = dc->w.charExtra;
676     dc->w.charExtra = abs(extra);
677     return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
678 }
679
680
681 /***********************************************************************
682  *           SetTextJustification    (GDI.10)
683  */
684 short SetTextJustification( HDC hdc, short extra, short breaks )
685 {
686     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
687     if (!dc) return 0;
688
689     extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
690     if (!extra) breaks = 0;
691     dc->w.breakTotalExtra = extra;
692     dc->w.breakCount = breaks;
693     if (breaks)
694     {   
695         dc->w.breakExtra = extra / breaks;
696         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
697     }
698     else
699     {
700         dc->w.breakExtra = 0;
701         dc->w.breakRem   = 0;
702     }
703     return 1;
704 }
705
706
707 /***********************************************************************
708  *           GetTextFace    (GDI.92)
709  */
710 INT GetTextFace( HDC hdc, INT count, LPSTR name )
711 {
712     FONTOBJ *font;
713
714     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
715     if (!dc) return 0;
716     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
717         return 0;
718     lstrcpyn32A( name, font->logfont.lfFaceName, count );
719     return strlen(name);
720 }
721
722
723 /***********************************************************************
724  *           GetTextExtent    (GDI.91)
725  */
726 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
727 {
728     SIZE16 size;
729     if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
730     return MAKELONG( size.cx, size.cy );
731 }
732
733
734 /***********************************************************************
735  *           GetTextExtentPoint16    (GDI.471)
736  */
737 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
738 {
739     SIZE32 size32;
740     BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
741     CONV_SIZE32TO16( &size32, size );
742     return (BOOL16)ret;
743 }
744
745
746 /***********************************************************************
747  *           GetTextExtentPoint32A    (GDI32.232)
748  */
749 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
750                               LPSIZE32 size )
751 {
752     int dir, ascent, descent;
753     XCharStruct info;
754
755     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
756     if (!dc) return FALSE;
757     XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
758                   &ascent, &descent, &info );
759     size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
760                     * dc->w.WndExtX / dc->w.VportExtX);
761     size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
762                     * dc->w.WndExtY / dc->w.VportExtY);
763
764     dprintf_font(stddeb,"GetTextExtentPoint(%08x '%*.*s' %d %p): returning %d,%d\n",
765                  hdc, count, count, str, count, size, size->cx, size->cy );
766     return TRUE;
767 }
768
769
770 /***********************************************************************
771  *           GetTextExtentPoint32W    (GDI32.233)
772  */
773 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
774                               LPSIZE32 size )
775 {
776     char *p = STRING32_DupUniToAnsi( str );
777     BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
778     free( p );
779     return ret;
780 }
781
782
783 /***********************************************************************
784  *           GetTextMetrics16    (GDI.93)
785  */
786 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
787 {
788     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
789     if (!dc) return FALSE;
790     memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
791
792     metrics->tmAscent  = abs( metrics->tmAscent
793                               * dc->w.WndExtY / dc->w.VportExtY );
794     metrics->tmDescent = abs( metrics->tmDescent
795                               * dc->w.WndExtY / dc->w.VportExtY );
796     metrics->tmHeight  = metrics->tmAscent + metrics->tmDescent;
797     metrics->tmInternalLeading = abs( metrics->tmInternalLeading
798                                       * dc->w.WndExtY / dc->w.VportExtY );
799     metrics->tmExternalLeading = abs( metrics->tmExternalLeading
800                                       * dc->w.WndExtY / dc->w.VportExtY );
801     metrics->tmMaxCharWidth    = abs( metrics->tmMaxCharWidth 
802                                       * dc->w.WndExtX / dc->w.VportExtX );
803     metrics->tmAveCharWidth    = abs( metrics->tmAveCharWidth
804                                       * dc->w.WndExtX / dc->w.VportExtX );
805
806     dprintf_font(stdnimp,"text metrics:\n
807         InternalLeading = %i
808         ExternalLeading = %i
809         MaxCharWidth = %i
810         Weight = %i
811         Italic = %i
812         Underlined = %i
813         StruckOut = %i
814         FirstChar = %i
815         LastChar = %i
816         DefaultChar = %i
817         BreakChar = %i
818         CharSet = %i
819         Overhang = %i
820         DigitizedAspectX = %i
821         DigitizedAspectY = %i
822         AveCharWidth = %i
823         MaxCharWidth = %i
824         Ascent = %i
825         Descent = %i
826         Height = %i\n",
827     metrics->tmInternalLeading,
828     metrics->tmExternalLeading,
829     metrics->tmMaxCharWidth,
830     metrics->tmWeight,
831     metrics->tmItalic,
832     metrics->tmUnderlined,
833     metrics->tmStruckOut,
834     metrics->tmFirstChar,
835     metrics->tmLastChar,
836     metrics->tmDefaultChar,
837     metrics->tmBreakChar,
838     metrics->tmCharSet,
839     metrics->tmOverhang,
840     metrics->tmDigitizedAspectX,
841     metrics->tmDigitizedAspectY,
842     metrics->tmAveCharWidth,
843     metrics->tmMaxCharWidth,
844     metrics->tmAscent,
845     metrics->tmDescent,
846     metrics->tmHeight);
847
848     return TRUE;
849 }
850
851
852 /***********************************************************************
853  *           GetTextMetrics32A    (GDI32.236)
854  */
855 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
856 {
857     TEXTMETRIC16 tm;
858     if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
859     metrics->tmHeight           = tm.tmHeight;
860     metrics->tmAscent           = tm.tmAscent;
861     metrics->tmDescent          = tm.tmDescent;
862     metrics->tmInternalLeading  = tm.tmInternalLeading;
863     metrics->tmExternalLeading  = tm.tmExternalLeading;
864     metrics->tmAveCharWidth     = tm.tmAveCharWidth;
865     metrics->tmMaxCharWidth     = tm.tmMaxCharWidth;
866     metrics->tmWeight           = tm.tmWeight;
867     metrics->tmOverhang         = tm.tmOverhang;
868     metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
869     metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
870     metrics->tmFirstChar        = tm.tmFirstChar;
871     metrics->tmLastChar         = tm.tmLastChar;
872     metrics->tmDefaultChar      = tm.tmDefaultChar;
873     metrics->tmBreakChar        = tm.tmBreakChar;
874     metrics->tmItalic           = tm.tmItalic;
875     metrics->tmUnderlined       = tm.tmUnderlined;
876     metrics->tmStruckOut        = tm.tmStruckOut;
877     metrics->tmPitchAndFamily   = tm.tmPitchAndFamily;
878     metrics->tmCharSet          = tm.tmCharSet;
879     return TRUE;
880 }
881
882
883 /***********************************************************************
884  *           GetTextMetrics32W    (GDI32.237)
885  */
886 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
887 {
888     TEXTMETRIC16 tm;
889     if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
890     metrics->tmHeight           = tm.tmHeight;
891     metrics->tmAscent           = tm.tmAscent;
892     metrics->tmDescent          = tm.tmDescent;
893     metrics->tmInternalLeading  = tm.tmInternalLeading;
894     metrics->tmExternalLeading  = tm.tmExternalLeading;
895     metrics->tmAveCharWidth     = tm.tmAveCharWidth;
896     metrics->tmMaxCharWidth     = tm.tmMaxCharWidth;
897     metrics->tmWeight           = tm.tmWeight;
898     metrics->tmOverhang         = tm.tmOverhang;
899     metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
900     metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
901     metrics->tmFirstChar        = tm.tmFirstChar;
902     metrics->tmLastChar         = tm.tmLastChar;
903     metrics->tmDefaultChar      = tm.tmDefaultChar;
904     metrics->tmBreakChar        = tm.tmBreakChar;
905     metrics->tmItalic           = tm.tmItalic;
906     metrics->tmUnderlined       = tm.tmUnderlined;
907     metrics->tmStruckOut        = tm.tmStruckOut;
908     metrics->tmPitchAndFamily   = tm.tmPitchAndFamily;
909     metrics->tmCharSet          = tm.tmCharSet;
910     return TRUE;
911 }
912
913
914 /***********************************************************************
915  *           SetMapperFlags    (GDI.349)
916  */
917 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
918 {
919     dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n", 
920                  hDC, dwFlag); 
921     return 0L;
922 }
923
924  
925 /***********************************************************************
926  *           GetCharABCWidths   (GDI.307)
927  */
928 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
929 {
930
931     /* No TrueType fonts in Wine so far */
932
933     fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
934                            hdc,wFirstChar,wLastChar,(unsigned)lpABC);
935   
936     return FALSE;
937 }
938
939
940 /***********************************************************************
941  *           GetCharWidth    (GDI.350)
942  */
943 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
944 {
945     int i, j;
946     XFontStruct *xfont;
947     XCharStruct *cs, *def;
948
949     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
950     if (!dc) return FALSE;
951     xfont = dc->u.x.font.fstruct;
952     
953     /* fixed font? */
954     if (xfont->per_char == NULL)
955     {
956         for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
957             *(lpBuffer + j) = xfont->max_bounds.width;
958         return TRUE;
959     }
960
961     CI_GET_DEFAULT_INFO(xfont, def);
962         
963     for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
964     {
965         CI_GET_CHAR_INFO(xfont, i, def, cs);
966         *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
967         if (*(lpBuffer + j) < 0)
968             *(lpBuffer + j) = 0;
969     }
970     return TRUE;
971 }
972
973
974 /***********************************************************************
975  *           AddFontResource    (GDI.119)
976  */
977 INT AddFontResource( LPCSTR str )
978 {
979     fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
980     return 1;
981 }
982
983
984 /***********************************************************************
985  *           RemoveFontResource    (GDI.136)
986  */
987 BOOL RemoveFontResource( LPSTR str )
988 {
989     fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
990     return TRUE;
991 }
992
993
994 /*************************************************************************
995  *                              ParseFontParms          [internal]
996  */
997 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
998 {
999         int     i;
1000         if (lpFont == NULL) return 0;
1001         if (lpRetStr == NULL) return 0;
1002         for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1003                 if (*lpFont == '-') i++;
1004                 lpFont++;
1005                 }
1006         if (i == wParmsNo) {
1007                 if (*lpFont == '-') lpFont++;
1008                 wMaxSiz--;
1009                 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1010                         *(lpRetStr + i) = *lpFont++;
1011                 *(lpRetStr + i) = '\0';
1012                 return i;
1013                 }
1014         else
1015                 lpRetStr[0] = '\0';
1016         return 0;
1017 }
1018
1019
1020 /*************************************************************************
1021  *                              InitFontsList           [internal]
1022  */
1023
1024 static int logfcmp(const void *a,const void *b) 
1025 {
1026   return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1027                  (*(LPLOGFONT16 *)b)->lfFaceName );
1028 }
1029
1030 void InitFontsList(void)
1031 {
1032   char  str[32];
1033   char  pattern[100];
1034   char  *family, *weight, *charset;
1035   char  **names;
1036   char  slant, spacing;
1037   int   i, count;
1038   LPLOGFONT16 lpNewFont;
1039
1040   dprintf_font(stddeb,"InitFontsList !\n");
1041
1042   weight = "medium";
1043   slant = 'r';
1044   spacing = '*';
1045   charset = "*";
1046   family = "*-*";
1047
1048   sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1049           family, weight, slant, spacing, charset);
1050   names = XListFonts( display, pattern, MAX_FONTS, &count );
1051   dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1052
1053   lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1054   if (lpNewFont == NULL) {
1055       dprintf_font(stddeb,
1056                    "InitFontsList // Error alloc new font structure !\n");
1057       XFreeFontNames(names);
1058       return;
1059   }
1060
1061   for (i = 0; i < count; i++) {
1062     dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1063
1064     ParseFontParms(names[i], 2, str, sizeof(str));
1065 #if 0
1066     /* not necessary because new function FONT_ChkX11Family() */
1067     if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1068 #endif    
1069     AnsiUpper(str);
1070     strcpy(lpNewFont->lfFaceName, str);
1071     ParseFontParms(names[i], 8, str, sizeof(str));
1072     lpNewFont->lfHeight = atoi(str) / 10;
1073     ParseFontParms(names[i], 12, str, sizeof(str));
1074     lpNewFont->lfWidth = atoi(str) / 10;
1075     lpNewFont->lfEscapement = 0;
1076     lpNewFont->lfOrientation = 0;
1077     lpNewFont->lfWeight = FW_REGULAR;
1078     lpNewFont->lfItalic = 0;
1079     lpNewFont->lfUnderline = 0;
1080     lpNewFont->lfStrikeOut = 0;
1081     ParseFontParms(names[i], 13, str, sizeof(str));
1082     if (strcmp(str, "iso8859") == 0)  {
1083       lpNewFont->lfCharSet = ANSI_CHARSET;
1084     } else  {
1085       lpNewFont->lfCharSet = OEM_CHARSET;
1086     }
1087     lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1088     lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1089     lpNewFont->lfQuality = DEFAULT_QUALITY;
1090     ParseFontParms(names[i], 11, str, sizeof(str));
1091     switch(str[0]) {
1092      case 'p':
1093       lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1094       break;
1095      case 'm':
1096      case 'c':
1097       lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1098       break;
1099      default:
1100       lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1101       break;
1102     }
1103     dprintf_font( stddeb,
1104                   "InitFontsList // lpNewFont->lfHeight=%d\n",
1105                   lpNewFont->lfHeight );
1106     dprintf_font( stddeb,
1107                   "InitFontsList // lpNewFont->lfWidth=%d\n",
1108                   lpNewFont->lfWidth );
1109     dprintf_font( stddeb,
1110                   "InitFontsList // lfFaceName='%s'\n",
1111                   lpNewFont->lfFaceName );
1112     lpLogFontList[i] = lpNewFont;
1113     lpNewFont = (LPLOGFONT16)
1114       ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1115   }
1116   lpLogFontList[i] = NULL;
1117
1118   qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1119   XFreeFontNames(names);
1120 }
1121
1122
1123 /*************************************************************************
1124  *                              EnumFonts                       [GDI.70]
1125  */
1126 INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1127 {
1128   HANDLE       hLog;
1129   HANDLE       hMet;
1130   HFONT        hFont;
1131   HFONT        hOldFont;
1132   LPLOGFONT16  lpLogFont;
1133   LPTEXTMETRIC16 lptm;
1134   LPSTR        lpOldName;
1135   char         FaceName[LF_FACESIZE];
1136   int          nRet = 0;
1137   int          i;
1138
1139   dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n", 
1140                hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
1141   if (lpEnumFunc == 0) return 0;
1142   hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
1143   lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1144   if (lpLogFont == NULL) {
1145     fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
1146     return 0;
1147   }
1148   hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1149   lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1150   if (lptm == NULL) {
1151     GDI_HEAP_FREE(hLog);
1152     fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1153     return 0;
1154   }
1155   if (lpFaceName != NULL) {
1156     strcpy(FaceName, lpFaceName);
1157     AnsiUpper(FaceName);
1158   } 
1159   lpOldName = NULL;
1160   
1161   if (lpLogFontList[0] == NULL) InitFontsList();
1162   for(i = 0; lpLogFontList[i] != NULL; i++) {
1163     if (lpFaceName == NULL) {
1164       if (lpOldName != NULL) {
1165         if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1166       }
1167       lpOldName = lpLogFontList[i]->lfFaceName;
1168     } else {
1169       if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1170     }
1171     dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1172     dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1173     memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
1174     hFont = CreateFontIndirect16(lpLogFont);
1175     hOldFont = SelectObject(hDC, hFont);
1176     GetTextMetrics16(hDC, lptm);
1177     SelectObject(hDC, hOldFont);
1178     DeleteObject(hFont);
1179     dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1180     nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1181                        0, (LONG)lpData );
1182     if (nRet == 0) {
1183       dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1184       break;
1185     }
1186   }
1187   GDI_HEAP_FREE(hMet);
1188   GDI_HEAP_FREE(hLog);
1189   return nRet;
1190 }
1191
1192
1193 /*************************************************************************
1194  *                              EnumFontFamilies        [GDI.330]
1195  */
1196 INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1197 {
1198   HANDLE        hLog;
1199   HANDLE        hMet;
1200   HFONT         hFont;
1201   HFONT         hOldFont;
1202   LPENUMLOGFONT16 lpEnumLogFont;
1203   LPTEXTMETRIC16 lptm;
1204   LPSTR         lpOldName;
1205   char          FaceName[LF_FACESIZE];
1206   int           nRet = 0;
1207   int           i;
1208   
1209   dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1210                hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1211   if (lpEnumFunc == 0) return 0;
1212   hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
1213   lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1214   if (lpEnumLogFont == NULL) {
1215     fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1216     return 0;
1217   }
1218   hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1219   lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1220   if (lptm == NULL) {
1221     GDI_HEAP_FREE(hLog);
1222     fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1223     return 0;
1224   }
1225   lpOldName = NULL;
1226   if (lpszFamily != NULL) {
1227     strcpy(FaceName, lpszFamily);
1228     AnsiUpper(FaceName);
1229   }
1230   if (lpLogFontList[0] == NULL) InitFontsList();
1231   for(i = 0; lpLogFontList[i] != NULL; i++) {
1232     if (lpszFamily == NULL) {
1233       if (lpOldName != NULL) {
1234         if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1235       }
1236       lpOldName = lpLogFontList[i]->lfFaceName;
1237     } else {
1238       if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1239     }
1240     memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1241     strcpy(lpEnumLogFont->elfFullName,"");
1242     strcpy(lpEnumLogFont->elfStyle,"");
1243     hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1244     hOldFont = SelectObject(hDC, hFont);
1245     GetTextMetrics16(hDC, lptm);
1246     SelectObject(hDC, hOldFont);
1247     DeleteObject(hFont);
1248     dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1249     
1250     nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1251                        0, lpData );
1252     if (nRet == 0) {
1253       dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1254       break;
1255     }
1256   }
1257   GDI_HEAP_FREE(hMet);
1258   GDI_HEAP_FREE(hLog);
1259   return nRet;
1260 }
1261
1262 /*************************************************************************
1263  *                              GetRasterizerCaps       [GDI.313]
1264  */
1265
1266 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1267 {
1268   /* This is not much more than a dummy */
1269   RASTERIZER_STATUS rs;
1270   
1271   rs.nSize = sizeof(rs);
1272   rs.wFlags = 0;
1273   rs.nLanguageID = 0;
1274   return True;
1275 }
1276
1277 /*************************************************************************
1278  *             GetKerningPairs      [GDI.332]
1279  */
1280 int GetKerningPairs(HDC hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1281 {
1282     /* This has to be dealt with when proper font handling is in place 
1283      *
1284      * At this time kerning is ignored (set to 0)
1285      */
1286
1287     int i;
1288     fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1289     for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1290     return 0;
1291 }