Release 941017
[wine/gsoc-2012-control.git] / objects / font.c
blob1a28d6c64bdd3899f1410c5daa8bed839fbb81d5
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"
15 #include "stddebug.h"
16 /* #define DEBUG_FONT /* */
17 /* #undef DEBUG_FONT /* */
18 #include "debug.h"
20 #define MAX_FONTS 256
21 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
24 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
25 (((cs)->rbearing|(cs)->lbearing| \
26 (cs)->ascent|(cs)->descent) == 0))
28 /*
29 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
30 * character. If the character is in the column and exists, then return the
31 * appropriate metrics (note that fonts with common per-character metrics will
32 * return min_bounds). If none of these hold true, try again with the default
33 * char.
35 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
36 { \
37 cs = def; \
38 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
39 if (fs->per_char == NULL) { \
40 cs = &fs->min_bounds; \
41 } else { \
42 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
43 if (CI_NONEXISTCHAR(cs)) cs = def; \
44 } \
45 } \
48 #define CI_GET_DEFAULT_INFO(fs,cs) \
49 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
52 /***********************************************************************
53 * FONT_TranslateName
55 * Translate a Windows face name to its X11 equivalent.
56 * This will probably have to be customizable.
58 static const char *FONT_TranslateName( char *winFaceName )
60 int i;
61 static const char *mappings[] =
63 /*Windows name*/ /*X11 name*/
64 "system", "helvetica",
65 "ms sans serif", "helvetica",
66 "ms serif", "times",
67 "fixedsys", "fixed",
68 "arial", "helvetica",
69 "helv", "helvetica",
70 "roman", "times"
73 for (i = 0; i < sizeof(mappings)/sizeof(mappings[0]); i += 2)
74 if (!strcmp( winFaceName, mappings[i] ))
76 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, mappings[i+1] );
77 return mappings[i+1];
79 return winFaceName;
83 /***********************************************************************
84 * FONT_MatchFont
86 * Find a X font matching the logical font.
88 static XFontStruct * FONT_MatchFont( LOGFONT * font )
90 char pattern[100];
91 const char *family, *weight, *charset;
92 char **names;
93 char slant, spacing;
94 int width, height, count;
95 XFontStruct * fontStruct;
97 weight = (font->lfWeight > 550) ? "bold" : "medium";
98 slant = font->lfItalic ? 'i' : 'r';
99 height = abs(font->lfHeight * 10);
100 width = font->lfWidth * 10;
101 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
102 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
103 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
104 if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
105 else switch(font->lfPitchAndFamily & 0xf0)
107 case FF_ROMAN: family = "times"; break;
108 case FF_SWISS: family = "helvetica"; break;
109 case FF_MODERN: family = "courier"; break;
110 case FF_SCRIPT: family = "*"; break;
111 case FF_DECORATIVE: family = "*"; break;
112 default: family = "*"; break;
115 while (TRUE) {
116 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
117 if ( width == 0 )
118 sprintf( pattern, "-*-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
119 family, weight, slant, height, spacing, charset);
120 else
121 sprintf( pattern, "-*-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
122 family, weight, slant, height, spacing, width, charset);
123 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
124 names = XListFonts( display, pattern, 1, &count );
125 if (count > 0) break;
126 height -= 10;
127 if (height < 10) {
128 dprintf_font(stddeb,"*** No match for %s\n", pattern );
129 return NULL;
132 dprintf_font(stddeb," Found '%s'\n", *names );
133 fontStruct = XLoadQueryFont( display, *names );
134 XFreeFontNames( names );
135 return fontStruct;
139 /***********************************************************************
140 * FONT_GetMetrics
142 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
143 TEXTMETRIC * metrics )
145 int average, i, count;
146 unsigned long prop;
148 metrics->tmAscent = xfont->ascent;
149 metrics->tmDescent = xfont->descent;
150 metrics->tmHeight = xfont->ascent + xfont->descent;
152 metrics->tmInternalLeading = 0;
153 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
154 metrics->tmInternalLeading = xfont->ascent - (short)prop;
155 metrics->tmExternalLeading = 0;
156 metrics->tmMaxCharWidth = xfont->max_bounds.width;
157 metrics->tmWeight = logfont->lfWeight;
158 metrics->tmItalic = logfont->lfItalic;
159 metrics->tmUnderlined = logfont->lfUnderline;
160 metrics->tmStruckOut = logfont->lfStrikeOut;
161 metrics->tmFirstChar = xfont->min_char_or_byte2;
162 metrics->tmLastChar = xfont->max_char_or_byte2;
163 metrics->tmDefaultChar = xfont->default_char;
164 metrics->tmBreakChar = ' ';
165 metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
166 metrics->tmCharSet = logfont->lfCharSet;
167 metrics->tmOverhang = 0;
168 metrics->tmDigitizedAspectX = 1;
169 metrics->tmDigitizedAspectY = 1;
171 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
172 else
174 XCharStruct * charPtr = xfont->per_char;
175 average = count = 0;
176 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
178 if (!CI_NONEXISTCHAR( charPtr ))
180 average += charPtr->width;
181 count++;
183 charPtr++;
185 if (count) average = (average + count/2) / count;
187 metrics->tmAveCharWidth = average;
191 /***********************************************************************
192 * CreateFontIndirect (GDI.57)
194 HFONT CreateFontIndirect( LOGFONT * font )
196 FONTOBJ * fontPtr;
197 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
198 if (!hfont) return 0;
199 fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
200 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
201 AnsiLower( fontPtr->logfont.lfFaceName );
202 dprintf_font(stddeb,"CreateFontIndirect(%08X); return %04X\n",font,hfont);
203 return hfont;
207 /***********************************************************************
208 * CreateFont (GDI.56)
210 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
211 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
212 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
213 LPSTR name )
215 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
216 strikeout, charset, outpres, clippres, quality, pitch, };
217 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
218 return CreateFontIndirect( &logfont );
222 /***********************************************************************
223 * FONT_GetObject
225 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
227 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
228 memcpy( buffer, &font->logfont, count );
229 return count;
233 /***********************************************************************
234 * FONT_SelectObject
236 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
238 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
239 X_PHYSFONT * stockPtr;
240 HFONT prevHandle = dc->w.hFont;
241 XFontStruct * fontStruct;
242 dprintf_font(stddeb,"FONT_SelectObject(%04X, %04X, %08X); !\n",
243 dc, hfont, font);
244 /* Load font if necessary */
246 if (!font)
248 HFONT hnewfont;
250 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
251 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
252 DEFAULT_QUALITY, FF_DONTCARE, "*" );
253 font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
256 if (dc->header.wMagic == METAFILE_DC_MAGIC)
257 return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
259 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
260 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
261 else
262 stockPtr = NULL;
264 if (!stockPtr || !stockPtr->fstruct)
266 fontStruct = FONT_MatchFont( &font->logfont );
268 else
270 fontStruct = stockPtr->fstruct;
271 dprintf_font(stddeb,
272 "FONT_SelectObject: Loaded font from cache %x %p\n",
273 hfont, fontStruct );
275 if (!fontStruct) return 0;
277 /* Free previous font */
279 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
281 if (dc->u.x.font.fstruct)
282 XFreeFont( display, dc->u.x.font.fstruct );
285 /* Store font */
287 dc->w.hFont = hfont;
288 if (stockPtr)
290 if (!stockPtr->fstruct)
292 stockPtr->fstruct = fontStruct;
293 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
295 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
297 else
299 dc->u.x.font.fstruct = fontStruct;
300 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
302 return prevHandle;
306 /***********************************************************************
307 * GetTextCharacterExtra (GDI.89)
309 short GetTextCharacterExtra( HDC hdc )
311 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
312 if (!dc) return 0;
313 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
314 / dc->w.VportExtX );
318 /***********************************************************************
319 * SetTextCharacterExtra (GDI.8)
321 short SetTextCharacterExtra( HDC hdc, short extra )
323 short prev;
324 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
325 if (!dc) return 0;
326 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
327 prev = dc->w.charExtra;
328 dc->w.charExtra = abs(extra);
329 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
333 /***********************************************************************
334 * SetTextJustification (GDI.10)
336 short SetTextJustification( HDC hdc, short extra, short breaks )
338 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
339 if (!dc) return 0;
341 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
342 if (!extra) breaks = 0;
343 dc->w.breakTotalExtra = extra;
344 dc->w.breakCount = breaks;
345 if (breaks)
347 dc->w.breakExtra = extra / breaks;
348 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
350 else
352 dc->w.breakExtra = 0;
353 dc->w.breakRem = 0;
355 return 1;
359 /***********************************************************************
360 * GetTextFace (GDI.92)
362 INT GetTextFace( HDC hdc, INT count, LPSTR name )
364 FONTOBJ *font;
366 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
367 if (!dc) return 0;
368 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
369 return 0;
370 strncpy( name, font->logfont.lfFaceName, count );
371 name[count-1] = '\0';
372 return strlen(name);
376 /***********************************************************************
377 * GetTextExtent (GDI.91)
379 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
381 SIZE size;
382 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
383 return size.cx | (size.cy << 16);
387 /***********************************************************************
388 * GetTextExtentPoint (GDI.471)
390 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
392 int dir, ascent, descent;
393 XCharStruct info;
395 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
396 if (!dc) return FALSE;
397 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
398 &ascent, &descent, &info );
399 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
400 * dc->w.WndExtX / dc->w.VportExtX);
401 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
402 * dc->w.WndExtY / dc->w.VportExtY);
404 dprintf_font(stddeb,"GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
405 hdc, str, count, size, size->cx, size->cy );
406 return TRUE;
410 /***********************************************************************
411 * GetTextMetrics (GDI.93)
413 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
415 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
416 if (!dc) return FALSE;
417 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
419 metrics->tmAscent = abs( metrics->tmAscent
420 * dc->w.WndExtY / dc->w.VportExtY );
421 metrics->tmDescent = abs( metrics->tmDescent
422 * dc->w.WndExtY / dc->w.VportExtY );
423 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
424 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
425 * dc->w.WndExtY / dc->w.VportExtY );
426 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
427 * dc->w.WndExtY / dc->w.VportExtY );
428 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
429 * dc->w.WndExtX / dc->w.VportExtX );
430 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
431 * dc->w.WndExtX / dc->w.VportExtX );
432 return TRUE;
436 /***********************************************************************
437 * SetMapperFlags (GDI.349)
439 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
441 dprintf_font(stdnimp,"SetmapperFlags(%04X, %08X) // Empty Stub !\n",
442 hDC, dwFlag);
443 return 0L;
447 /***********************************************************************/
450 /***********************************************************************
451 * GetCharWidth (GDI.350)
453 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
455 int i, j;
456 XFontStruct *xfont;
457 XCharStruct *cs, *def;
459 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
460 if (!dc) return FALSE;
461 xfont = dc->u.x.font.fstruct;
463 /* fixed font? */
464 if (xfont->per_char == NULL)
466 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
467 *(lpBuffer + j) = xfont->max_bounds.width;
468 return TRUE;
471 CI_GET_DEFAULT_INFO(xfont, def);
473 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
475 CI_GET_CHAR_INFO(xfont, i, def, cs);
476 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
477 if (*(lpBuffer + j) < 0)
478 *(lpBuffer + j) = 0;
480 return TRUE;
483 /*************************************************************************
484 * ParseFontParms [internal]
486 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
488 int i, j;
489 dprintf_font(stddeb,"ParseFontParms('%s', %d, %08X, %d);\n",
490 lpFont, wParmsNo, lpRetStr, wMaxSiz);
491 if (lpFont == NULL) return 0;
492 if (lpRetStr == NULL) return 0;
493 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
494 if (*lpFont == '-') i++;
495 lpFont++;
497 if (i == wParmsNo) {
498 if (*lpFont == '-') lpFont++;
499 wMaxSiz--;
500 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
501 *(lpRetStr + i) = *lpFont++;
502 *(lpRetStr + i) = '\0';
503 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
504 return i;
506 else
507 lpRetStr[0] = '\0';
508 return 0;
512 /*************************************************************************
513 * InitFontsList [internal]
515 void InitFontsList()
517 char str[32];
518 char pattern[100];
519 char *family, *weight, *charset;
520 char **names;
521 char slant, spacing;
522 int i, width, count;
523 LPLOGFONT lpNewFont;
524 weight = "medium";
525 slant = 'r';
526 spacing = '*';
527 charset = "*";
528 family = "*";
529 dprintf_font(stddeb,"InitFontsList !\n");
530 sprintf( pattern, "-*-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
531 family, weight, slant, spacing, charset);
532 names = XListFonts( display, pattern, MAX_FONTS, &count );
533 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
534 for (i = 0; i < count; i++) {
535 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
536 if (lpNewFont == NULL) {
537 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
538 break;
540 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
541 ParseFontParms(names[i], 2, str, sizeof(str));
542 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
543 AnsiUpper(str);
544 strcpy(lpNewFont->lfFaceName, str);
545 ParseFontParms(names[i], 7, str, sizeof(str));
546 lpNewFont->lfHeight = atoi(str) / 10;
547 ParseFontParms(names[i], 12, str, sizeof(str));
548 lpNewFont->lfWidth = atoi(str) / 10;
549 lpNewFont->lfEscapement = 0;
550 lpNewFont->lfOrientation = 0;
551 lpNewFont->lfWeight = FW_REGULAR;
552 lpNewFont->lfItalic = 0;
553 lpNewFont->lfUnderline = 0;
554 lpNewFont->lfStrikeOut = 0;
555 ParseFontParms(names[i], 13, str, sizeof(str));
556 if (strcmp(str, "iso8859") == 0)
557 lpNewFont->lfCharSet = ANSI_CHARSET;
558 else
559 lpNewFont->lfCharSet = OEM_CHARSET;
560 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
561 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
562 lpNewFont->lfQuality = DEFAULT_QUALITY;
563 ParseFontParms(names[i], 11, str, sizeof(str));
564 switch(str[0]) {
565 case 'p':
566 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
567 break;
568 case 'm':
569 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
570 break;
571 default:
572 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
573 break;
575 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
576 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
577 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
578 lpLogFontList[i] = lpNewFont;
579 lpLogFontList[i+1] = NULL;
581 XFreeFontNames(names);
585 /*************************************************************************
586 * EnumFonts [GDI.70]
588 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
590 HANDLE hLog;
591 HANDLE hMet;
592 HFONT hFont;
593 HFONT hOldFont;
594 LPLOGFONT lpLogFont;
595 LPTEXTMETRIC lptm;
596 LPSTR lpFaceList[MAX_FONTS];
597 char FaceName[LF_FACESIZE];
598 int nRet;
599 int j, i = 0;
601 dprintf_font(stddeb,"EnumFonts(%04X, %08X='%s', %08X, %08X)\n",
602 hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
603 if (lpEnumFunc == NULL) return 0;
604 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
605 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
606 if (lpLogFont == NULL) {
607 dprintf_font(stddeb,"EnumFonts // can't alloc LOGFONT struct !\n");
608 return 0;
610 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
611 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
612 if (lptm == NULL) {
613 USER_HEAP_FREE(hLog);
614 dprintf_font(stddeb, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
615 return 0;
617 if (lpFaceName != NULL) {
618 strcpy(FaceName, lpFaceName);
619 AnsiUpper(FaceName);
621 if (lpLogFontList[0] == NULL) InitFontsList();
622 memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
623 while (TRUE) {
624 if (lpLogFontList[i] == NULL) break;
625 if (lpFaceName == NULL) {
626 for (j = 0; j < MAX_FONTS; j++) {
627 if (lpFaceList[j] == NULL) break;
628 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
629 i++; j = 0;
630 if (lpLogFontList[i] == NULL) break;
633 if (lpLogFontList[i] == NULL) break;
634 lpFaceList[j] = lpLogFontList[i]->lfFaceName;
635 dprintf_font(stddeb,"EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
637 else {
638 while(lpLogFontList[i] != NULL) {
639 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
640 i++;
642 if (lpLogFontList[i] == NULL) break;
644 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
645 hFont = CreateFontIndirect(lpLogFont);
646 hOldFont = SelectObject(hDC, hFont);
647 GetTextMetrics(hDC, lptm);
648 SelectObject(hDC, hOldFont);
649 DeleteObject(hFont);
650 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
652 #ifdef WINELIB
653 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
654 #else
655 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
656 2, (int)lptm, 0, (int)0, 2, (int)lpData);
657 #endif
658 if (nRet == 0) {
659 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
660 break;
663 USER_HEAP_FREE(hMet);
664 USER_HEAP_FREE(hLog);
665 return 0;
669 /*************************************************************************
670 * EnumFontFamilies [GDI.330]
672 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
674 HANDLE hLog;
675 HANDLE hMet;
676 HFONT hFont;
677 HFONT hOldFont;
678 LPLOGFONT lpLogFont;
679 LPTEXTMETRIC lptm;
680 LPSTR lpFaceList[MAX_FONTS];
681 char FaceName[LF_FACESIZE];
682 int nRet;
683 int j, i = 0;
685 dprintf_font(stddeb,"EnumFontFamilies(%04X, %08X, %08X, %08X)\n",
686 hDC, lpszFamily, lpEnumFunc, lpData);
687 if (lpEnumFunc == NULL) return 0;
688 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
689 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
690 if (lpLogFont == NULL) {
691 dprintf_font(stddeb,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
692 return 0;
694 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
695 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
696 if (lptm == NULL) {
697 USER_HEAP_FREE(hLog);
698 dprintf_font(stddeb,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
699 return 0;
701 if (lpszFamily != NULL) {
702 strcpy(FaceName, lpszFamily);
703 AnsiUpper(FaceName);
705 if (lpLogFontList[0] == NULL) InitFontsList();
706 memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
707 while (TRUE) {
708 if (lpLogFontList[i] == NULL) break;
709 if (lpszFamily == NULL) {
710 if (lpLogFontList[i] == NULL) break;
711 for (j = 0; j < MAX_FONTS; j++) {
712 if (lpFaceList[j] == NULL) break;
713 if (lpLogFontList[i] == NULL) break;
714 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
715 i++; j = 0;
718 if (lpLogFontList[i] == NULL) break;
719 lpFaceList[j] = lpLogFontList[i]->lfFaceName;
720 dprintf_font(stddeb,"EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
722 else {
723 while(lpLogFontList[i] != NULL) {
724 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
725 i++;
727 if (lpLogFontList[i] == NULL) break;
729 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
730 hFont = CreateFontIndirect(lpLogFont);
731 hOldFont = SelectObject(hDC, hFont);
732 GetTextMetrics(hDC, lptm);
733 SelectObject(hDC, hOldFont);
734 DeleteObject(hFont);
735 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
737 #ifdef WINELIB
738 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
739 #else
740 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
741 2, (int)lptm, 0, (int)0, 2, (int)lpData);
742 #endif
743 if (nRet == 0) {
744 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
745 break;
748 USER_HEAP_FREE(hMet);
749 USER_HEAP_FREE(hLog);
750 return 0;