Release 941210
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <X11/Xatom.h>
13 #include "user.h"
14 #include "gdi.h"
15 #include "metafile.h"
16 #include "callback.h"
17 #include "stddebug.h"
18 /* #define DEBUG_FONT */
19 #include "debug.h"
20
21 #define MAX_FONTS       256
22 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
23
24
25 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
26                              (((cs)->rbearing|(cs)->lbearing| \
27                                (cs)->ascent|(cs)->descent) == 0))
28
29 /* 
30  * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
31  * character.  If the character is in the column and exists, then return the
32  * appropriate metrics (note that fonts with common per-character metrics will
33  * return min_bounds).  If none of these hold true, try again with the default
34  * char.
35  */
36 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
37 { \
38     cs = def; \
39     if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
40         if (fs->per_char == NULL) { \
41             cs = &fs->min_bounds; \
42         } else { \
43             cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
44             if (CI_NONEXISTCHAR(cs)) cs = def; \
45         } \
46     } \
47 }
48
49 #define CI_GET_DEFAULT_INFO(fs,cs) \
50   CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
51
52 struct FontStructure {
53         char *window;
54         char *x11;
55 } FontNames[32];
56 int FontSize;
57
58 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
59  *           Font_Init
60  */
61
62 void Font_Init( void )
63 {
64   char  temp[1024];
65   LPSTR ptr;
66   int i;
67
68   if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) {
69     for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
70       if( strcmp( ptr, "default" ) )
71         FontNames[i++].window = strdup( ptr );
72     FontSize = i;
73
74     for( i = 1; i < FontSize; i++ ) {
75       GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI);
76       FontNames[i].x11 = strdup( temp );
77     }
78     GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI);
79     FontNames[0].x11 = strdup( temp );
80
81   } else {
82     FontNames[0].window = NULL; FontNames[0].x11 = "bitstream-courier";
83     FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
84     FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
85     FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
86     FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
87     FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
88     FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
89     FontSize = 7;
90   }
91 }
92
93 /***********************************************************************
94  *           FONT_TranslateName
95  *
96  * Translate a Windows face name to its X11 equivalent.
97  * This will probably have to be customizable.
98  */
99 static const char *FONT_TranslateName( char *winFaceName )
100 {
101   int i;
102
103   for (i = 1; i < FontSize; i ++)
104     if( !strcmp( winFaceName, FontNames[i].window ) ) {
105       dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
106       return FontNames[i].x11;
107     }
108   return FontNames[0].x11;
109 }
110
111
112 /***********************************************************************
113  *           FONT_MatchFont
114  *
115  * Find a X font matching the logical font.
116  */
117 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
118 {
119     char pattern[100];
120     const char *family, *weight, *charset;
121     char **names;
122     char slant, spacing;
123     int width, height, count;
124     XFontStruct * fontStruct;
125     
126     weight = (font->lfWeight > 550) ? "bold" : "medium";
127     slant = font->lfItalic ? 'i' : 'r';
128     height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
129     if (height == 0) height = 120;  /* Default height = 12 */
130     else if (height < 0)
131     {
132           /* If height is negative, it means the height of the characters */
133           /* *without* the internal leading. So we adjust it a bit to     */
134           /* compensate. 5/4 seems to give good results for small fonts.  */
135         height = 10 * (-height * 5 / 4);
136     }
137     else height *= 10;
138     width  = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
139     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
140               (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
141     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
142     if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
143     else switch(font->lfPitchAndFamily & 0xf0)
144     {
145     case FF_ROMAN:
146       family = FONT_TranslateName( "roman" );
147       break;
148     case FF_SWISS:
149       family = FONT_TranslateName( "swiss" );
150       break;
151     case FF_MODERN:
152       family = FONT_TranslateName( "modern" );
153       break;
154     case FF_SCRIPT:
155       family = FONT_TranslateName( "script" );
156       break;
157     case FF_DECORATIVE:
158       family = FONT_TranslateName( "decorative" );
159       break;
160     default:
161       family = "*-*";
162       break;
163     }
164     
165         while (TRUE) {
166             /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
167             if ( width == 0 )
168               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
169                       family, weight, slant, height, spacing, charset);
170             else
171               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
172                       family, weight, slant, height, spacing, width, charset);
173             dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
174             names = XListFonts( display, pattern, 1, &count );
175             if (count > 0) break;
176             height -= 10;               
177             if (height < 10) {
178                 dprintf_font(stddeb,"*** No match for %s\n", pattern );
179                 return NULL;
180             }
181         }
182     dprintf_font(stddeb,"        Found '%s'\n", *names );
183     fontStruct = XLoadQueryFont( display, *names );
184     XFreeFontNames( names );
185     return fontStruct;
186 }
187
188
189 /***********************************************************************
190  *           FONT_GetMetrics
191  */
192 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
193                       TEXTMETRIC * metrics )
194 {    
195     int average, i, count;
196     unsigned long prop;
197         
198     metrics->tmAscent  = xfont->ascent;
199     metrics->tmDescent = xfont->descent;
200     metrics->tmHeight  = xfont->ascent + xfont->descent;
201
202     metrics->tmInternalLeading  = 0;
203     if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
204         metrics->tmInternalLeading = xfont->ascent - (short)prop;
205     metrics->tmExternalLeading  = 0;
206     metrics->tmMaxCharWidth     = xfont->max_bounds.width;
207     metrics->tmWeight           = logfont->lfWeight;
208     metrics->tmItalic           = logfont->lfItalic;
209     metrics->tmUnderlined       = logfont->lfUnderline;
210     metrics->tmStruckOut        = logfont->lfStrikeOut;
211     metrics->tmFirstChar        = xfont->min_char_or_byte2;
212     metrics->tmLastChar         = xfont->max_char_or_byte2;
213     metrics->tmDefaultChar      = xfont->default_char;
214     metrics->tmBreakChar        = ' ';
215     metrics->tmPitchAndFamily   = logfont->lfPitchAndFamily;
216     metrics->tmCharSet          = logfont->lfCharSet;
217     metrics->tmOverhang         = 0;
218     metrics->tmDigitizedAspectX = 1;
219     metrics->tmDigitizedAspectY = 1;
220
221     if (!xfont->per_char) average = metrics->tmMaxCharWidth;
222     else
223     {
224         XCharStruct * charPtr = xfont->per_char;
225         average = count = 0;
226         for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
227         {
228             if (!CI_NONEXISTCHAR( charPtr ))
229             {
230                 average += charPtr->width;
231                 count++;
232             }
233             charPtr++;
234         }
235         if (count) average = (average + count/2) / count;
236     }
237     metrics->tmAveCharWidth = average;
238 }
239
240
241 /***********************************************************************
242  *           CreateFontIndirect    (GDI.57)
243  */
244 HFONT CreateFontIndirect( LOGFONT * font )
245 {
246     FONTOBJ * fontPtr;
247     HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
248     if (!hfont) return 0;
249     fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
250     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
251     AnsiLower( fontPtr->logfont.lfFaceName );
252     dprintf_font(stddeb,"CreateFontIndirect(%p); return %04x\n",font,hfont);
253     return hfont;
254 }
255
256
257 /***********************************************************************
258  *           CreateFont    (GDI.56)
259  */
260 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
261                   BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
262                   BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
263                   LPSTR name )
264 {
265     LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
266                     strikeout, charset, outpres, clippres, quality, pitch, };
267     strncpy( logfont.lfFaceName, name, LF_FACESIZE );
268     return CreateFontIndirect( &logfont );
269 }
270
271
272 /***********************************************************************
273  *           FONT_GetObject
274  */
275 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
276 {
277     if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
278     memcpy( buffer, &font->logfont, count );
279     return count;
280 }
281
282
283 /***********************************************************************
284  *           FONT_SelectObject
285  */
286 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
287 {
288     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
289     X_PHYSFONT * stockPtr;
290     HFONT prevHandle = dc->w.hFont;
291     XFontStruct * fontStruct;
292     dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", 
293                      dc, hfont, font);
294       /* Load font if necessary */
295
296     if (!font)
297     {
298         HFONT hnewfont;
299
300         hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
301                               FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
302                               DEFAULT_QUALITY, FF_DONTCARE, "*" );
303         font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
304     }
305
306     if (dc->header.wMagic == METAFILE_DC_MAGIC)
307         return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
308
309     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
310         stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
311     else 
312         stockPtr = NULL;
313     
314     if (!stockPtr || !stockPtr->fstruct)
315     {
316         fontStruct = FONT_MatchFont( &font->logfont, dc );
317     }
318     else
319     {
320         fontStruct = stockPtr->fstruct;
321         dprintf_font(stddeb, 
322                      "FONT_SelectObject: Loaded font from cache %x %p\n",
323                      hfont, fontStruct );
324     }   
325     if (!fontStruct) return 0;
326
327       /* Free previous font */
328
329     if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
330     {
331         if (dc->u.x.font.fstruct)
332             XFreeFont( display, dc->u.x.font.fstruct );
333     }
334
335       /* Store font */
336
337     dc->w.hFont = hfont;
338     if (stockPtr)
339     {
340         if (!stockPtr->fstruct)
341         {
342             stockPtr->fstruct = fontStruct;
343             FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
344         }
345         memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
346     }
347     else
348     {
349         dc->u.x.font.fstruct = fontStruct;
350         FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
351     }
352     return prevHandle;
353 }
354
355
356 /***********************************************************************
357  *           GetTextCharacterExtra    (GDI.89)
358  */
359 short GetTextCharacterExtra( HDC hdc )
360 {
361     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
362     if (!dc) return 0;
363     return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
364                  / dc->w.VportExtX );
365 }
366
367
368 /***********************************************************************
369  *           SetTextCharacterExtra    (GDI.8)
370  */
371 short SetTextCharacterExtra( HDC hdc, short extra )
372 {
373     short prev;
374     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
375     if (!dc) return 0;
376     extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;    
377     prev = dc->w.charExtra;
378     dc->w.charExtra = abs(extra);
379     return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
380 }
381
382
383 /***********************************************************************
384  *           SetTextJustification    (GDI.10)
385  */
386 short SetTextJustification( HDC hdc, short extra, short breaks )
387 {
388     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
389     if (!dc) return 0;
390
391     extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
392     if (!extra) breaks = 0;
393     dc->w.breakTotalExtra = extra;
394     dc->w.breakCount = breaks;
395     if (breaks)
396     {   
397         dc->w.breakExtra = extra / breaks;
398         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
399     }
400     else
401     {
402         dc->w.breakExtra = 0;
403         dc->w.breakRem   = 0;
404     }
405     return 1;
406 }
407
408
409 /***********************************************************************
410  *           GetTextFace    (GDI.92)
411  */
412 INT GetTextFace( HDC hdc, INT count, LPSTR name )
413 {
414     FONTOBJ *font;
415
416     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
417     if (!dc) return 0;
418     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
419         return 0;
420     strncpy( name, font->logfont.lfFaceName, count );
421     name[count-1] = '\0';
422     return strlen(name);
423 }
424
425
426 /***********************************************************************
427  *           GetTextExtent    (GDI.91)
428  */
429 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
430 {
431     SIZE size;
432     if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
433     return MAKELONG( size.cx, size.cy );
434 }
435
436
437 /***********************************************************************
438  *           GetTextExtentPoint    (GDI.471)
439  */
440 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
441 {
442     int dir, ascent, descent;
443     XCharStruct info;
444
445     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
446     if (!dc) return FALSE;
447     XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
448                   &ascent, &descent, &info );
449     size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
450                     * dc->w.WndExtX / dc->w.VportExtX);
451     size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
452                     * dc->w.WndExtY / dc->w.VportExtY);
453
454     dprintf_font(stddeb,"GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
455             hdc, str, count, size, size->cx, size->cy );
456     return TRUE;
457 }
458
459
460 /***********************************************************************
461  *           GetTextMetrics    (GDI.93)
462  */
463 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
464 {
465     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
466     if (!dc) return FALSE;
467     memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
468
469     metrics->tmAscent  = abs( metrics->tmAscent
470                               * dc->w.WndExtY / dc->w.VportExtY );
471     metrics->tmDescent = abs( metrics->tmDescent
472                               * dc->w.WndExtY / dc->w.VportExtY );
473     metrics->tmHeight  = metrics->tmAscent + metrics->tmDescent;
474     metrics->tmInternalLeading = abs( metrics->tmInternalLeading
475                                       * dc->w.WndExtY / dc->w.VportExtY );
476     metrics->tmExternalLeading = abs( metrics->tmExternalLeading
477                                       * dc->w.WndExtY / dc->w.VportExtY );
478     metrics->tmMaxCharWidth    = abs( metrics->tmMaxCharWidth 
479                                       * dc->w.WndExtX / dc->w.VportExtX );
480     metrics->tmAveCharWidth    = abs( metrics->tmAveCharWidth
481                                       * dc->w.WndExtX / dc->w.VportExtX );
482     return TRUE;
483 }
484
485
486 /***********************************************************************
487  *           SetMapperFlags    (GDI.349)
488  */
489 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
490 {
491     dprintf_font(stdnimp,"SetmapperFlags(%04X, %08lX) // Empty Stub !\n", 
492                  hDC, dwFlag); 
493     return 0L;
494 }
495
496  
497 /***********************************************************************/
498
499
500 /***********************************************************************
501  *           GetCharWidth    (GDI.350)
502  */
503 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
504 {
505     int i, j;
506     XFontStruct *xfont;
507     XCharStruct *cs, *def;
508
509     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
510     if (!dc) return FALSE;
511     xfont = dc->u.x.font.fstruct;
512     
513     /* fixed font? */
514     if (xfont->per_char == NULL)
515     {
516         for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
517             *(lpBuffer + j) = xfont->max_bounds.width;
518         return TRUE;
519     }
520
521     CI_GET_DEFAULT_INFO(xfont, def);
522         
523     for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
524     {
525         CI_GET_CHAR_INFO(xfont, i, def, cs);
526         *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
527         if (*(lpBuffer + j) < 0)
528             *(lpBuffer + j) = 0;
529     }
530     return TRUE;
531 }
532
533
534 /***********************************************************************
535  *           AddFontResource    (GDI.119)
536  */
537 int AddFontResource( LPSTR str )
538 {
539     fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
540     return 1;
541 }
542
543
544 /***********************************************************************
545  *           RemoveFontResource    (GDI.136)
546  */
547 BOOL RemoveFontResource( LPSTR str )
548 {
549     fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
550     return TRUE;
551 }
552
553
554 /*************************************************************************
555  *                              ParseFontParms          [internal]
556  */
557 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
558 {
559         int     i;
560         dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n", 
561                         lpFont, wParmsNo, lpRetStr, wMaxSiz);
562         if (lpFont == NULL) return 0;
563         if (lpRetStr == NULL) return 0;
564         for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
565                 if (*lpFont == '-') i++;
566                 lpFont++;
567                 }
568         if (i == wParmsNo) {
569                 if (*lpFont == '-') lpFont++;
570                 wMaxSiz--;
571                 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
572                         *(lpRetStr + i) = *lpFont++;
573                 *(lpRetStr + i) = '\0';
574                 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
575                 return i;
576                 }
577         else
578                 lpRetStr[0] = '\0';
579         return 0;
580 }
581
582
583 /*************************************************************************
584  *                              InitFontsList           [internal]
585  */
586 void InitFontsList(void)
587 {
588     char        str[32];
589     char        pattern[100];
590     char        *family, *weight, *charset;
591         char    **names;
592     char        slant, spacing;
593     int         i, count;
594         LPLOGFONT       lpNewFont;
595     weight = "medium";
596     slant = 'r';
597     spacing = '*';
598     charset = "*";
599     family = "*-*";
600     dprintf_font(stddeb,"InitFontsList !\n");
601     sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
602               family, weight, slant, spacing, charset);
603     names = XListFonts( display, pattern, MAX_FONTS, &count );
604     dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
605         for (i = 0; i < count; i++) {
606                 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
607                 if (lpNewFont == NULL) {
608                         dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
609                         break;
610                         }
611                 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
612                 ParseFontParms(names[i], 2, str, sizeof(str));
613                 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
614                 AnsiUpper(str);
615                 strcpy(lpNewFont->lfFaceName, str);
616                 ParseFontParms(names[i], 7, str, sizeof(str));
617                 lpNewFont->lfHeight = atoi(str) / 10;
618                 ParseFontParms(names[i], 12, str, sizeof(str));
619                 lpNewFont->lfWidth = atoi(str) / 10;
620                 lpNewFont->lfEscapement = 0;
621                 lpNewFont->lfOrientation = 0;
622                 lpNewFont->lfWeight = FW_REGULAR;
623                 lpNewFont->lfItalic = 0;
624                 lpNewFont->lfUnderline = 0;
625                 lpNewFont->lfStrikeOut = 0;
626                 ParseFontParms(names[i], 13, str, sizeof(str));
627                 if (strcmp(str, "iso8859") == 0)
628                         lpNewFont->lfCharSet = ANSI_CHARSET;
629                 else
630                         lpNewFont->lfCharSet = OEM_CHARSET;
631                 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
632                 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
633                 lpNewFont->lfQuality = DEFAULT_QUALITY;
634                 ParseFontParms(names[i], 11, str, sizeof(str));
635                 switch(str[0]) {
636                         case 'p':
637                                 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
638                                 break;
639                         case 'm':
640                                 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
641                                 break;
642                         default:
643                                 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
644                                 break;
645                         }
646                 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
647                 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
648                 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
649                 lpLogFontList[i] = lpNewFont;
650                 lpLogFontList[i+1] = NULL;
651                 }
652     XFreeFontNames(names);
653 }
654
655
656 /*************************************************************************
657  *                              EnumFonts                       [GDI.70]
658  */
659 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
660 {
661         HANDLE                  hLog;
662         HANDLE                  hMet;
663         HFONT                   hFont;
664         HFONT                   hOldFont;
665         LPLOGFONT               lpLogFont;
666         LPTEXTMETRIC    lptm;
667         LPSTR                   lpFaceList[MAX_FONTS];
668         char                    FaceName[LF_FACESIZE];
669         int                             nRet;
670         int                             j, i = 0;
671
672         dprintf_font(stddeb,"EnumFonts(%04X, %08X='%s', %08X, %08X)\n", 
673                 hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
674         if (lpEnumFunc == NULL) return 0;
675         hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
676         lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
677         if (lpLogFont == NULL) {
678                 dprintf_font(stddeb,"EnumFonts // can't alloc LOGFONT struct !\n");
679                 return 0;
680                 }
681         hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
682         lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
683         if (lptm == NULL) {
684                 USER_HEAP_FREE(hLog);
685                 dprintf_font(stddeb, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
686                 return 0;
687                 }
688         if (lpFaceName != NULL) {
689                 strcpy(FaceName, lpFaceName);
690                 AnsiUpper(FaceName);
691                 }
692         if (lpLogFontList[0] == NULL) InitFontsList();
693         memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
694         while (TRUE) {
695                 if (lpLogFontList[i] == NULL) break;
696                 if (lpFaceName == NULL) {
697                         for (j = 0; j < MAX_FONTS; j++) {
698                                 if (lpFaceList[j] == NULL) break;
699                                 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
700                                         i++; j = 0;
701                                         if (lpLogFontList[i] == NULL) break;
702                                         }
703                                 }
704                         if (lpLogFontList[i] == NULL) break;
705                         lpFaceList[j] = lpLogFontList[i]->lfFaceName;
706                         dprintf_font(stddeb,"EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
707                         }
708                 else {
709                         while(lpLogFontList[i] != NULL) {
710                                 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
711                                 i++;
712                                 }
713                         if (lpLogFontList[i] == NULL) break;
714                         }
715                 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
716                 hFont = CreateFontIndirect(lpLogFont);
717                 hOldFont = SelectObject(hDC, hFont);
718                 GetTextMetrics(hDC, lptm);
719                 SelectObject(hDC, hOldFont);
720                 DeleteObject(hFont);
721                 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
722
723 #ifdef WINELIB
724                 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
725 #else
726                 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
727                                         2, (int)lptm, 0, (int)0, 2, (int)lpData);
728 #endif
729                 if (nRet == 0) {
730                         dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
731                         break;
732                         }
733                 }
734         USER_HEAP_FREE(hMet);
735         USER_HEAP_FREE(hLog);
736         return 0;
737 }
738
739
740 /*************************************************************************
741  *                              EnumFontFamilies        [GDI.330]
742  */
743 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
744 {
745         HANDLE                  hLog;
746         HANDLE                  hMet;
747         HFONT                   hFont;
748         HFONT                   hOldFont;
749         LPLOGFONT               lpLogFont;
750         LPTEXTMETRIC    lptm;
751         LPSTR                   lpFaceList[MAX_FONTS];
752         char                    FaceName[LF_FACESIZE];
753         int                             nRet;
754         int                             j, i = 0;
755
756         dprintf_font(stddeb,"EnumFontFamilies(%04X, %08X, %08X, %08X)\n", 
757                                         hDC, lpszFamily, lpEnumFunc, lpData);
758         if (lpEnumFunc == NULL) return 0;
759         hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
760         lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
761         if (lpLogFont == NULL) {
762                 dprintf_font(stddeb,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
763                 return 0;
764                 }
765         hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
766         lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
767         if (lptm == NULL) {
768                 USER_HEAP_FREE(hLog);
769                 dprintf_font(stddeb,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
770                 return 0;
771                 }
772         if (lpszFamily != NULL) {
773                 strcpy(FaceName, lpszFamily);
774                 AnsiUpper(FaceName);
775                 }
776         if (lpLogFontList[0] == NULL) InitFontsList();
777         memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
778         while (TRUE) {
779                 if (lpLogFontList[i] == NULL) break;
780                 if (lpszFamily == NULL) {
781                         if (lpLogFontList[i] == NULL) break;
782                         for (j = 0; j < MAX_FONTS; j++) {
783                                 if (lpFaceList[j] == NULL) break;
784                                 if (lpLogFontList[i] == NULL) break;
785                                 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
786                                         i++; j = 0;
787                                         }
788                                 }
789                         if (lpLogFontList[i] == NULL) break;
790                         lpFaceList[j] = lpLogFontList[i]->lfFaceName;
791                         dprintf_font(stddeb,"EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
792                         }
793                 else {
794                         while(lpLogFontList[i] != NULL) {
795                                 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
796                                 i++;
797                                 }
798                         if (lpLogFontList[i] == NULL) break;
799                         }
800                 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
801                 hFont = CreateFontIndirect(lpLogFont);
802                 hOldFont = SelectObject(hDC, hFont);
803                 GetTextMetrics(hDC, lptm);
804                 SelectObject(hDC, hOldFont);
805                 DeleteObject(hFont);
806                 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
807
808 #ifdef WINELIB
809                 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
810 #else
811                 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
812                                         2, (int)lptm, 0, (int)0, 2, (int)lpData);
813 #endif
814                 if (nRet == 0) {
815                         dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
816                         break;
817                         }
818                 }
819         USER_HEAP_FREE(hMet);
820         USER_HEAP_FREE(hLog);
821         return 0;
822 }
823
824
825