Release 940722
[wine/multimedia.git] / objects / font.c
blob3f3b4cb0434f360125b115b8089b34c45d2168aa
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
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"
16 #define MAX_FONTS 256
17 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
20 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
21 (((cs)->rbearing|(cs)->lbearing| \
22 (cs)->ascent|(cs)->descent) == 0))
24 /*
25 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
26 * character. If the character is in the column and exists, then return the
27 * appropriate metrics (note that fonts with common per-character metrics will
28 * return min_bounds). If none of these hold true, try again with the default
29 * char.
31 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
32 { \
33 cs = def; \
34 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
35 if (fs->per_char == NULL) { \
36 cs = &fs->min_bounds; \
37 } else { \
38 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
39 if (CI_NONEXISTCHAR(cs)) cs = def; \
40 } \
41 } \
44 #define CI_GET_DEFAULT_INFO(fs,cs) \
45 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
47 /***********************************************************************
48 * FONT_MatchFont
50 * Find a X font matching the logical font.
52 static XFontStruct * FONT_MatchFont( LOGFONT * font )
54 char pattern[100];
55 char *family, *weight, *charset;
56 char **names;
57 char slant, spacing;
58 int width, height, count;
59 XFontStruct * fontStruct;
61 weight = (font->lfWeight > 550) ? "bold" : "medium";
62 slant = font->lfItalic ? 'i' : 'r';
63 height = font->lfHeight * 10;
64 width = font->lfWidth * 10;
65 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
66 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
67 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
68 family = font->lfFaceName;
69 if (!*family) switch(font->lfPitchAndFamily & 0xf0)
71 case FF_ROMAN: family = "times"; break;
72 case FF_SWISS: family = "helvetica"; break;
73 case FF_MODERN: family = "courier"; break;
74 case FF_SCRIPT: family = "*"; break;
75 case FF_DECORATIVE: family = "*"; break;
76 default: family = "*"; break;
78 else
79 AnsiLower(family);
81 while (TRUE) {
82 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
83 if ( width == 0 )
84 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-*-%s",
85 family, weight, slant, height, spacing, charset);
86 else
87 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
88 family, weight, slant, height, spacing, width, charset);
89 #ifdef DEBUG_FONT
90 printf( "FONT_MatchFont: '%s'\n", pattern );
91 #endif
92 names = XListFonts( XT_display, pattern, 1, &count );
93 if (count > 0) break;
94 height -= 10;
95 if (height < 10) {
96 #ifdef DEBUG_FONT
97 printf( " No matching font found\n" );
98 #endif
99 return NULL;
102 #ifdef DEBUG_FONT
103 printf( " Found '%s'\n", *names );
104 #endif
105 fontStruct = XLoadQueryFont( XT_display, *names );
106 XFreeFontNames( names );
107 return fontStruct;
111 /***********************************************************************
112 * FONT_GetMetrics
114 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
115 TEXTMETRIC * metrics )
117 int average, i, count;
118 unsigned long prop;
120 metrics->tmAscent = xfont->ascent;
121 metrics->tmDescent = xfont->descent;
122 metrics->tmHeight = xfont->ascent + xfont->descent;
124 metrics->tmInternalLeading = 0;
125 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
126 metrics->tmInternalLeading = xfont->ascent - (short)prop;
127 metrics->tmExternalLeading = 0;
128 metrics->tmMaxCharWidth = xfont->max_bounds.width;
129 metrics->tmWeight = logfont->lfWeight;
130 metrics->tmItalic = logfont->lfItalic;
131 metrics->tmUnderlined = logfont->lfUnderline;
132 metrics->tmStruckOut = logfont->lfStrikeOut;
133 metrics->tmFirstChar = xfont->min_char_or_byte2;
134 metrics->tmLastChar = xfont->max_char_or_byte2;
135 metrics->tmDefaultChar = xfont->default_char;
136 metrics->tmBreakChar = ' ';
137 metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
138 metrics->tmCharSet = logfont->lfCharSet;
139 metrics->tmOverhang = 0;
140 metrics->tmDigitizedAspectX = 1;
141 metrics->tmDigitizedAspectY = 1;
143 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
144 else
146 XCharStruct * charPtr = xfont->per_char;
147 average = count = 0;
148 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
150 if (!CI_NONEXISTCHAR( charPtr ))
152 average += charPtr->width;
153 count++;
155 charPtr++;
157 if (count) average = (average + count/2) / count;
159 metrics->tmAveCharWidth = average;
163 /***********************************************************************
164 * CreateFontIndirect (GDI.57)
166 HFONT CreateFontIndirect( LOGFONT * font )
168 FONTOBJ * fontPtr;
169 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
170 if (!hfont) return 0;
171 fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
172 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
173 #ifdef DEBUG_FONT
174 printf("CreateFontIndirect(%08X); return %04X !\n", font, hfont);
175 #endif
176 return hfont;
180 /***********************************************************************
181 * CreateFont (GDI.56)
183 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
184 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
185 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
186 LPSTR name )
188 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
189 strikeout, charset, outpres, clippres, quality, pitch, };
190 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
191 return CreateFontIndirect( &logfont );
195 /***********************************************************************
196 * FONT_GetObject
198 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
200 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
201 memcpy( buffer, &font->logfont, count );
202 return count;
206 /***********************************************************************
207 * FONT_SelectObject
209 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
211 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
212 X_PHYSFONT * stockPtr;
213 HFONT prevHandle = dc->w.hFont;
214 XFontStruct * fontStruct;
215 #ifdef DEBUG_FONT
216 printf("FONT_SelectObject(%04X, %04X, %08X); !\n", dc, hfont, font);
217 #endif
218 /* Load font if necessary */
220 if (!font)
222 HFONT hnewfont;
224 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
225 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
226 DEFAULT_QUALITY, FF_DONTCARE, "*" );
227 font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
230 if (dc->header.wMagic == METAFILE_DC_MAGIC)
231 return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
233 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
234 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
235 else
236 stockPtr = NULL;
238 if (!stockPtr || !stockPtr->fstruct)
240 fontStruct = FONT_MatchFont( &font->logfont );
242 else
244 fontStruct = stockPtr->fstruct;
245 #ifdef DEBUG_FONT
246 printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
247 hfont, fontStruct );
248 #endif
250 if (!fontStruct) return 0;
252 /* Free previous font */
254 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
256 if (dc->u.x.font.fstruct)
257 XFreeFont( XT_display, dc->u.x.font.fstruct );
260 /* Store font */
262 dc->w.hFont = hfont;
263 if (stockPtr)
265 if (!stockPtr->fstruct)
267 stockPtr->fstruct = fontStruct;
268 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
270 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
272 else
274 dc->u.x.font.fstruct = fontStruct;
275 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
277 return prevHandle;
281 /***********************************************************************
282 * GetTextCharacterExtra (GDI.89)
284 short GetTextCharacterExtra( HDC hdc )
286 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
287 if (!dc) return 0;
288 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
289 / dc->w.VportExtX );
293 /***********************************************************************
294 * SetTextCharacterExtra (GDI.8)
296 short SetTextCharacterExtra( HDC hdc, short extra )
298 short prev;
299 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
300 if (!dc) return 0;
301 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
302 prev = dc->w.charExtra;
303 dc->w.charExtra = abs(extra);
304 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
308 /***********************************************************************
309 * SetTextJustification (GDI.10)
311 short SetTextJustification( HDC hdc, short extra, short breaks )
313 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
314 if (!dc) return 0;
316 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
317 if (!extra) breaks = 0;
318 dc->w.breakTotalExtra = extra;
319 dc->w.breakCount = breaks;
320 if (breaks)
322 dc->w.breakExtra = extra / breaks;
323 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
325 else
327 dc->w.breakExtra = 0;
328 dc->w.breakRem = 0;
330 return 1;
334 /***********************************************************************
335 * GetTextExtent (GDI.91)
337 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
339 SIZE size;
340 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
341 return size.cx | (size.cy << 16);
345 /***********************************************************************
346 * GetTextExtentPoint (GDI.471)
348 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
350 int dir, ascent, descent;
351 XCharStruct info;
353 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
354 if (!dc) return FALSE;
355 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
356 &ascent, &descent, &info );
357 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
358 * dc->w.WndExtX / dc->w.VportExtX);
359 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
360 * dc->w.WndExtY / dc->w.VportExtY);
362 #ifdef DEBUG_FONT
363 printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
364 hdc, str, count, size, size->cx, size->cy );
365 #endif
366 return TRUE;
370 /***********************************************************************
371 * GetTextMetrics (GDI.93)
373 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
375 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
376 if (!dc) return FALSE;
377 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
379 metrics->tmAscent = abs( metrics->tmAscent
380 * dc->w.WndExtY / dc->w.VportExtY );
381 metrics->tmDescent = abs( metrics->tmDescent
382 * dc->w.WndExtY / dc->w.VportExtY );
383 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
384 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
385 * dc->w.WndExtY / dc->w.VportExtY );
386 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
387 * dc->w.WndExtY / dc->w.VportExtY );
388 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
389 * dc->w.WndExtX / dc->w.VportExtX );
390 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
391 * dc->w.WndExtX / dc->w.VportExtX );
392 return TRUE;
396 /***********************************************************************
397 * SetMapperFlags (GDI.349)
399 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
401 printf("SetmapperFlags(%04X, %08X) // Empty Stub !\n", hDC, dwFlag);
402 return 0L;
406 /***********************************************************************/
409 /***********************************************************************
410 * GetCharWidth (GDI.350)
412 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
414 int i, j;
415 XFontStruct *xfont;
416 XCharStruct *cs, *def;
418 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
419 if (!dc) return FALSE;
420 xfont = dc->u.x.font.fstruct;
422 /* fixed font? */
423 if (xfont->per_char == NULL)
425 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
426 *(lpBuffer + j) = xfont->max_bounds.width;
427 return TRUE;
430 CI_GET_DEFAULT_INFO(xfont, def);
432 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
434 CI_GET_CHAR_INFO(xfont, i, def, cs);
435 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
436 if (*(lpBuffer + j) < 0)
437 *(lpBuffer + j) = 0;
439 return TRUE;
442 /*************************************************************************
443 * ParseFontParms [internal]
445 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
447 int i, j;
448 #ifdef DEBUG_FONT
449 printf("ParseFontParms('%s', %d, %08X, %d);\n",
450 lpFont, wParmsNo, lpRetStr, wMaxSiz);
451 #endif
452 if (lpFont == NULL) return 0;
453 if (lpRetStr == NULL) return 0;
454 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
455 if (*lpFont == '-') i++;
456 lpFont++;
458 if (i == wParmsNo) {
459 if (*lpFont == '-') lpFont++;
460 wMaxSiz--;
461 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
462 *(lpRetStr + i) = *lpFont++;
463 *(lpRetStr + i) = '\0';
464 #ifdef DEBUG_FONT
465 printf("ParseFontParms // '%s'\n", lpRetStr);
466 #endif
467 return i;
469 else
470 lpRetStr[0] = '\0';
471 return 0;
475 /*************************************************************************
476 * InitFontsList [internal]
478 void InitFontsList()
480 char str[32];
481 char pattern[100];
482 char *family, *weight, *charset;
483 char **names;
484 char slant, spacing;
485 int i, width, count;
486 LPLOGFONT lpNewFont;
487 weight = "medium";
488 slant = 'r';
489 spacing = '*';
490 charset = "*";
491 family = "*";
492 printf("InitFontsList !\n");
493 sprintf( pattern, "-*-%s-%s-%c-normal--*-*-*-*-%c-*-%s",
494 family, weight, slant, spacing, charset);
495 names = XListFonts( XT_display, pattern, MAX_FONTS, &count );
496 #ifdef DEBUG_FONT
497 printf("InitFontsList // count=%d \n", count);
498 #endif
499 for (i = 0; i < count; i++) {
500 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
501 if (lpNewFont == NULL) {
502 printf("InitFontsList // Error alloc new font structure !\n");
503 break;
505 #ifdef DEBUG_FONT
506 printf("InitFontsList // names[%d]='%s' \n", i, names[i]);
507 #endif
508 ParseFontParms(names[i], 2, str, sizeof(str));
509 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
510 AnsiUpper(str);
511 strcpy(lpNewFont->lfFaceName, str);
512 ParseFontParms(names[i], 7, str, sizeof(str));
513 lpNewFont->lfHeight = atoi(str) / 10;
514 ParseFontParms(names[i], 12, str, sizeof(str));
515 lpNewFont->lfWidth = atoi(str) / 10;
516 lpNewFont->lfEscapement = 0;
517 lpNewFont->lfOrientation = 0;
518 lpNewFont->lfWeight = FW_REGULAR;
519 lpNewFont->lfItalic = 0;
520 lpNewFont->lfUnderline = 0;
521 lpNewFont->lfStrikeOut = 0;
522 ParseFontParms(names[i], 13, str, sizeof(str));
523 if (strcmp(str, "iso8859") == 0)
524 lpNewFont->lfCharSet = ANSI_CHARSET;
525 else
526 lpNewFont->lfCharSet = OEM_CHARSET;
527 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
528 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
529 lpNewFont->lfQuality = DEFAULT_QUALITY;
530 ParseFontParms(names[i], 11, str, sizeof(str));
531 switch(str[0]) {
532 case 'p':
533 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
534 break;
535 case 'm':
536 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
537 break;
538 default:
539 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
540 break;
542 #ifdef DEBUG_FONT
543 printf("InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
544 printf("InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
545 printf("InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
546 #endif
547 lpLogFontList[i] = lpNewFont;
548 lpLogFontList[i+1] = NULL;
550 XFreeFontNames(names);
554 /*************************************************************************
555 * EnumFonts [GDI.70]
557 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
559 HANDLE hLog;
560 HANDLE hMet;
561 HFONT hFont;
562 HFONT hOldFont;
563 LPLOGFONT lpLogFont;
564 LPTEXTMETRIC lptm;
565 LPSTR lpFaceList[MAX_FONTS];
566 char FaceName[LF_FACESIZE];
567 int nRet;
568 int j, i = 0;
569 printf("EnumFonts(%04X, %08X='%s', %08X, %08X)\n",
570 hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
571 if (lpEnumFunc == NULL) return 0;
572 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
573 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
574 if (lpLogFont == NULL) {
575 printf("EnumFonts // can't alloc LOGFONT struct !\n");
576 return 0;
578 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
579 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
580 if (lptm == NULL) {
581 USER_HEAP_FREE(hLog);
582 printf("EnumFonts // can't alloc TEXTMETRIC struct !\n");
583 return 0;
585 if (lpFaceName != NULL) {
586 strcpy(FaceName, lpFaceName);
587 AnsiUpper(FaceName);
589 if (lpLogFontList[0] == NULL) InitFontsList();
590 memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
591 while (TRUE) {
592 if (lpLogFontList[i] == NULL) break;
593 if (lpFaceName == NULL) {
594 for (j = 0; j < MAX_FONTS; j++) {
595 if (lpFaceList[j] == NULL) break;
596 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
597 i++; j = 0;
598 if (lpLogFontList[i] == NULL) break;
601 if (lpLogFontList[i] == NULL) break;
602 lpFaceList[j] = lpLogFontList[i]->lfFaceName;
603 printf("EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
605 else {
606 while(lpLogFontList[i] != NULL) {
607 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
608 i++;
610 if (lpLogFontList[i] == NULL) break;
612 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
613 hFont = CreateFontIndirect(lpLogFont);
614 hOldFont = SelectObject(hDC, hFont);
615 GetTextMetrics(hDC, lptm);
616 SelectObject(hDC, hOldFont);
617 DeleteObject(hFont);
618 printf("EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
619 #ifdef WINELIB
620 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
621 #else
622 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
623 2, (int)lptm, 0, (int)0, 2, (int)lpData);
624 #endif
625 if (nRet == 0) {
626 printf("EnumFonts // EnumEnd requested by application !\n");
627 break;
630 USER_HEAP_FREE(hMet);
631 USER_HEAP_FREE(hLog);
632 return 0;
636 /*************************************************************************
637 * EnumFontFamilies [GDI.330]
639 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
641 HANDLE hLog;
642 HANDLE hMet;
643 HFONT hFont;
644 HFONT hOldFont;
645 LPLOGFONT lpLogFont;
646 LPTEXTMETRIC lptm;
647 LPSTR lpFaceList[MAX_FONTS];
648 char FaceName[LF_FACESIZE];
649 int nRet;
650 int j, i = 0;
651 printf("EnumFontFamilies(%04X, %08X, %08X, %08X)\n",
652 hDC, lpszFamily, lpEnumFunc, lpData);
653 if (lpEnumFunc == NULL) return 0;
654 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
655 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
656 if (lpLogFont == NULL) {
657 printf("EnumFontFamilies // can't alloc LOGFONT struct !\n");
658 return 0;
660 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
661 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
662 if (lptm == NULL) {
663 USER_HEAP_FREE(hLog);
664 printf("EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
665 return 0;
667 if (lpszFamily != NULL) {
668 strcpy(FaceName, lpszFamily);
669 AnsiUpper(FaceName);
671 if (lpLogFontList[0] == NULL) InitFontsList();
672 memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
673 while (TRUE) {
674 if (lpLogFontList[i] == NULL) break;
675 if (lpszFamily == NULL) {
676 if (lpLogFontList[i] == NULL) break;
677 for (j = 0; j < MAX_FONTS; j++) {
678 if (lpFaceList[j] == NULL) break;
679 if (lpLogFontList[i] == NULL) break;
680 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
681 i++; j = 0;
684 if (lpLogFontList[i] == NULL) break;
685 lpFaceList[j] = lpLogFontList[i]->lfFaceName;
686 printf("EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
688 else {
689 while(lpLogFontList[i] != NULL) {
690 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
691 i++;
693 if (lpLogFontList[i] == NULL) break;
695 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
696 hFont = CreateFontIndirect(lpLogFont);
697 hOldFont = SelectObject(hDC, hFont);
698 GetTextMetrics(hDC, lptm);
699 SelectObject(hDC, hOldFont);
700 DeleteObject(hFont);
701 printf("EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
702 #ifdef WINELIB
703 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
704 #else
705 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
706 2, (int)lptm, 0, (int)0, 2, (int)lpData);
707 #endif
708 if (nRet == 0) {
709 printf("EnumFontFamilies // EnumEnd requested by application !\n");
710 break;
713 USER_HEAP_FREE(hMet);
714 USER_HEAP_FREE(hLog);
715 return 0;