Release 941122
[wine/multimedia.git] / objects / font.c
blobf051b8a134055c89aeaefafe076c3338f6ff8c52
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)
51 struct FontStructure {
52 char *window;
53 char *x11;
54 } FontNames[32];
55 int FontSize;
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
58 * Font_Init
61 void Font_Init( void )
63 char temp[1024];
64 LPSTR ptr;
65 int i;
67 if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) {
68 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
69 if( strcmp( ptr, "default" ) )
70 FontNames[i++].window = strdup( ptr );
71 FontSize = i;
73 for( i = 1; i < FontSize; i++ ) {
74 GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI);
75 FontNames[i].x11 = strdup( temp );
77 GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI);
78 FontNames[0].x11 = strdup( temp );
80 } else {
81 FontNames[0].window = NULL; FontNames[0].x11 = "bitstream-courier";
82 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
83 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
84 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
85 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
86 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
87 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
88 FontSize = 7;
92 /***********************************************************************
93 * FONT_TranslateName
95 * Translate a Windows face name to its X11 equivalent.
96 * This will probably have to be customizable.
98 static const char *FONT_TranslateName( char *winFaceName )
100 int i;
102 for (i = 1; i < FontSize; i ++)
103 if( !strcmp( winFaceName, FontNames[i].window ) ) {
104 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
105 return FontNames[i].x11;
107 return FontNames[0].x11;
111 /***********************************************************************
112 * FONT_MatchFont
114 * Find a X font matching the logical font.
116 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
118 char pattern[100];
119 const char *family, *weight, *charset;
120 char **names;
121 char slant, spacing;
122 int width, height, count;
123 XFontStruct * fontStruct;
125 weight = (font->lfWeight > 550) ? "bold" : "medium";
126 slant = font->lfItalic ? 'i' : 'r';
127 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
128 if (height == 0) height = 120; /* Default height = 12 */
129 else if (height < 0)
131 /* If height is negative, it means the height of the characters */
132 /* *without* the internal leading. So we adjust it a bit to */
133 /* compensate. 5/4 seems to give good results for small fonts. */
134 height = 10 * (-height * 5 / 4);
136 else height *= 10;
137 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
138 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
139 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
140 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
141 if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
142 else switch(font->lfPitchAndFamily & 0xf0)
144 case FF_ROMAN:
145 family = FONT_TranslateName( "roman" );
146 break;
147 case FF_SWISS:
148 family = FONT_TranslateName( "swiss" );
149 break;
150 case FF_MODERN:
151 family = FONT_TranslateName( "modern" );
152 break;
153 case FF_SCRIPT:
154 family = FONT_TranslateName( "script" );
155 break;
156 case FF_DECORATIVE:
157 family = FONT_TranslateName( "decorative" );
158 break;
159 default:
160 family = "*-*";
161 break;
164 while (TRUE) {
165 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
166 if ( width == 0 )
167 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
168 family, weight, slant, height, spacing, charset);
169 else
170 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
171 family, weight, slant, height, spacing, width, charset);
172 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
173 names = XListFonts( display, pattern, 1, &count );
174 if (count > 0) break;
175 height -= 10;
176 if (height < 10) {
177 dprintf_font(stddeb,"*** No match for %s\n", pattern );
178 return NULL;
181 dprintf_font(stddeb," Found '%s'\n", *names );
182 fontStruct = XLoadQueryFont( display, *names );
183 XFreeFontNames( names );
184 return fontStruct;
188 /***********************************************************************
189 * FONT_GetMetrics
191 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
192 TEXTMETRIC * metrics )
194 int average, i, count;
195 unsigned long prop;
197 metrics->tmAscent = xfont->ascent;
198 metrics->tmDescent = xfont->descent;
199 metrics->tmHeight = xfont->ascent + xfont->descent;
201 metrics->tmInternalLeading = 0;
202 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
203 metrics->tmInternalLeading = xfont->ascent - (short)prop;
204 metrics->tmExternalLeading = 0;
205 metrics->tmMaxCharWidth = xfont->max_bounds.width;
206 metrics->tmWeight = logfont->lfWeight;
207 metrics->tmItalic = logfont->lfItalic;
208 metrics->tmUnderlined = logfont->lfUnderline;
209 metrics->tmStruckOut = logfont->lfStrikeOut;
210 metrics->tmFirstChar = xfont->min_char_or_byte2;
211 metrics->tmLastChar = xfont->max_char_or_byte2;
212 metrics->tmDefaultChar = xfont->default_char;
213 metrics->tmBreakChar = ' ';
214 metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
215 metrics->tmCharSet = logfont->lfCharSet;
216 metrics->tmOverhang = 0;
217 metrics->tmDigitizedAspectX = 1;
218 metrics->tmDigitizedAspectY = 1;
220 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
221 else
223 XCharStruct * charPtr = xfont->per_char;
224 average = count = 0;
225 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
227 if (!CI_NONEXISTCHAR( charPtr ))
229 average += charPtr->width;
230 count++;
232 charPtr++;
234 if (count) average = (average + count/2) / count;
236 metrics->tmAveCharWidth = average;
240 /***********************************************************************
241 * CreateFontIndirect (GDI.57)
243 HFONT CreateFontIndirect( LOGFONT * font )
245 FONTOBJ * fontPtr;
246 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
247 if (!hfont) return 0;
248 fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
249 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
250 AnsiLower( fontPtr->logfont.lfFaceName );
251 dprintf_font(stddeb,"CreateFontIndirect(%p); return %04x\n",font,hfont);
252 return hfont;
256 /***********************************************************************
257 * CreateFont (GDI.56)
259 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
260 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
261 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
262 LPSTR name )
264 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
265 strikeout, charset, outpres, clippres, quality, pitch, };
266 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
267 return CreateFontIndirect( &logfont );
271 /***********************************************************************
272 * FONT_GetObject
274 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
276 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
277 memcpy( buffer, &font->logfont, count );
278 return count;
282 /***********************************************************************
283 * FONT_SelectObject
285 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
287 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
288 X_PHYSFONT * stockPtr;
289 HFONT prevHandle = dc->w.hFont;
290 XFontStruct * fontStruct;
291 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n",
292 dc, hfont, font);
293 /* Load font if necessary */
295 if (!font)
297 HFONT hnewfont;
299 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
300 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
301 DEFAULT_QUALITY, FF_DONTCARE, "*" );
302 font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
305 if (dc->header.wMagic == METAFILE_DC_MAGIC)
306 return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
308 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
309 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
310 else
311 stockPtr = NULL;
313 if (!stockPtr || !stockPtr->fstruct)
315 fontStruct = FONT_MatchFont( &font->logfont, dc );
317 else
319 fontStruct = stockPtr->fstruct;
320 dprintf_font(stddeb,
321 "FONT_SelectObject: Loaded font from cache %x %p\n",
322 hfont, fontStruct );
324 if (!fontStruct) return 0;
326 /* Free previous font */
328 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
330 if (dc->u.x.font.fstruct)
331 XFreeFont( display, dc->u.x.font.fstruct );
334 /* Store font */
336 dc->w.hFont = hfont;
337 if (stockPtr)
339 if (!stockPtr->fstruct)
341 stockPtr->fstruct = fontStruct;
342 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
344 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
346 else
348 dc->u.x.font.fstruct = fontStruct;
349 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
351 return prevHandle;
355 /***********************************************************************
356 * GetTextCharacterExtra (GDI.89)
358 short GetTextCharacterExtra( HDC hdc )
360 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
361 if (!dc) return 0;
362 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
363 / dc->w.VportExtX );
367 /***********************************************************************
368 * SetTextCharacterExtra (GDI.8)
370 short SetTextCharacterExtra( HDC hdc, short extra )
372 short prev;
373 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
374 if (!dc) return 0;
375 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
376 prev = dc->w.charExtra;
377 dc->w.charExtra = abs(extra);
378 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
382 /***********************************************************************
383 * SetTextJustification (GDI.10)
385 short SetTextJustification( HDC hdc, short extra, short breaks )
387 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
388 if (!dc) return 0;
390 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
391 if (!extra) breaks = 0;
392 dc->w.breakTotalExtra = extra;
393 dc->w.breakCount = breaks;
394 if (breaks)
396 dc->w.breakExtra = extra / breaks;
397 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
399 else
401 dc->w.breakExtra = 0;
402 dc->w.breakRem = 0;
404 return 1;
408 /***********************************************************************
409 * GetTextFace (GDI.92)
411 INT GetTextFace( HDC hdc, INT count, LPSTR name )
413 FONTOBJ *font;
415 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
416 if (!dc) return 0;
417 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
418 return 0;
419 strncpy( name, font->logfont.lfFaceName, count );
420 name[count-1] = '\0';
421 return strlen(name);
425 /***********************************************************************
426 * GetTextExtent (GDI.91)
428 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
430 SIZE size;
431 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
432 return size.cx | (size.cy << 16);
436 /***********************************************************************
437 * GetTextExtentPoint (GDI.471)
439 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
441 int dir, ascent, descent;
442 XCharStruct info;
444 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
445 if (!dc) return FALSE;
446 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
447 &ascent, &descent, &info );
448 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
449 * dc->w.WndExtX / dc->w.VportExtX);
450 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
451 * dc->w.WndExtY / dc->w.VportExtY);
453 dprintf_font(stddeb,"GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
454 hdc, str, count, size, size->cx, size->cy );
455 return TRUE;
459 /***********************************************************************
460 * GetTextMetrics (GDI.93)
462 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
464 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
465 if (!dc) return FALSE;
466 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
468 metrics->tmAscent = abs( metrics->tmAscent
469 * dc->w.WndExtY / dc->w.VportExtY );
470 metrics->tmDescent = abs( metrics->tmDescent
471 * dc->w.WndExtY / dc->w.VportExtY );
472 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
473 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
474 * dc->w.WndExtY / dc->w.VportExtY );
475 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
476 * dc->w.WndExtY / dc->w.VportExtY );
477 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
478 * dc->w.WndExtX / dc->w.VportExtX );
479 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
480 * dc->w.WndExtX / dc->w.VportExtX );
481 return TRUE;
485 /***********************************************************************
486 * SetMapperFlags (GDI.349)
488 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
490 dprintf_font(stdnimp,"SetmapperFlags(%04X, %08lX) // Empty Stub !\n",
491 hDC, dwFlag);
492 return 0L;
496 /***********************************************************************/
499 /***********************************************************************
500 * GetCharWidth (GDI.350)
502 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
504 int i, j;
505 XFontStruct *xfont;
506 XCharStruct *cs, *def;
508 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
509 if (!dc) return FALSE;
510 xfont = dc->u.x.font.fstruct;
512 /* fixed font? */
513 if (xfont->per_char == NULL)
515 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
516 *(lpBuffer + j) = xfont->max_bounds.width;
517 return TRUE;
520 CI_GET_DEFAULT_INFO(xfont, def);
522 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
524 CI_GET_CHAR_INFO(xfont, i, def, cs);
525 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
526 if (*(lpBuffer + j) < 0)
527 *(lpBuffer + j) = 0;
529 return TRUE;
533 /***********************************************************************
534 * AddFontResource (GDI.119)
536 int AddFontResource( LPSTR str )
538 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
539 return 1;
543 /***********************************************************************
544 * RemoveFontResource (GDI.136)
546 BOOL RemoveFontResource( LPSTR str )
548 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
549 return TRUE;
553 /*************************************************************************
554 * ParseFontParms [internal]
556 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
558 int i;
559 dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n",
560 lpFont, wParmsNo, lpRetStr, wMaxSiz);
561 if (lpFont == NULL) return 0;
562 if (lpRetStr == NULL) return 0;
563 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
564 if (*lpFont == '-') i++;
565 lpFont++;
567 if (i == wParmsNo) {
568 if (*lpFont == '-') lpFont++;
569 wMaxSiz--;
570 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
571 *(lpRetStr + i) = *lpFont++;
572 *(lpRetStr + i) = '\0';
573 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
574 return i;
576 else
577 lpRetStr[0] = '\0';
578 return 0;
582 /*************************************************************************
583 * InitFontsList [internal]
585 void InitFontsList()
587 char str[32];
588 char pattern[100];
589 char *family, *weight, *charset;
590 char **names;
591 char slant, spacing;
592 int i, count;
593 LPLOGFONT lpNewFont;
594 weight = "medium";
595 slant = 'r';
596 spacing = '*';
597 charset = "*";
598 family = "*-*";
599 dprintf_font(stddeb,"InitFontsList !\n");
600 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
601 family, weight, slant, spacing, charset);
602 names = XListFonts( display, pattern, MAX_FONTS, &count );
603 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
604 for (i = 0; i < count; i++) {
605 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
606 if (lpNewFont == NULL) {
607 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
608 break;
610 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
611 ParseFontParms(names[i], 2, str, sizeof(str));
612 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
613 AnsiUpper(str);
614 strcpy(lpNewFont->lfFaceName, str);
615 ParseFontParms(names[i], 7, str, sizeof(str));
616 lpNewFont->lfHeight = atoi(str) / 10;
617 ParseFontParms(names[i], 12, str, sizeof(str));
618 lpNewFont->lfWidth = atoi(str) / 10;
619 lpNewFont->lfEscapement = 0;
620 lpNewFont->lfOrientation = 0;
621 lpNewFont->lfWeight = FW_REGULAR;
622 lpNewFont->lfItalic = 0;
623 lpNewFont->lfUnderline = 0;
624 lpNewFont->lfStrikeOut = 0;
625 ParseFontParms(names[i], 13, str, sizeof(str));
626 if (strcmp(str, "iso8859") == 0)
627 lpNewFont->lfCharSet = ANSI_CHARSET;
628 else
629 lpNewFont->lfCharSet = OEM_CHARSET;
630 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
631 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
632 lpNewFont->lfQuality = DEFAULT_QUALITY;
633 ParseFontParms(names[i], 11, str, sizeof(str));
634 switch(str[0]) {
635 case 'p':
636 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
637 break;
638 case 'm':
639 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
640 break;
641 default:
642 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
643 break;
645 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
646 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
647 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
648 lpLogFontList[i] = lpNewFont;
649 lpLogFontList[i+1] = NULL;
651 XFreeFontNames(names);
655 /*************************************************************************
656 * EnumFonts [GDI.70]
658 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
660 HANDLE hLog;
661 HANDLE hMet;
662 HFONT hFont;
663 HFONT hOldFont;
664 LPLOGFONT lpLogFont;
665 LPTEXTMETRIC lptm;
666 LPSTR lpFaceList[MAX_FONTS];
667 char FaceName[LF_FACESIZE];
668 int nRet;
669 int j, i = 0;
671 dprintf_font(stddeb,"EnumFonts(%04X, %08X='%s', %08X, %08X)\n",
672 hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
673 if (lpEnumFunc == NULL) return 0;
674 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
675 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
676 if (lpLogFont == NULL) {
677 dprintf_font(stddeb,"EnumFonts // can't alloc LOGFONT struct !\n");
678 return 0;
680 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
681 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
682 if (lptm == NULL) {
683 USER_HEAP_FREE(hLog);
684 dprintf_font(stddeb, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
685 return 0;
687 if (lpFaceName != NULL) {
688 strcpy(FaceName, lpFaceName);
689 AnsiUpper(FaceName);
691 if (lpLogFontList[0] == NULL) InitFontsList();
692 memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
693 while (TRUE) {
694 if (lpLogFontList[i] == NULL) break;
695 if (lpFaceName == NULL) {
696 for (j = 0; j < MAX_FONTS; j++) {
697 if (lpFaceList[j] == NULL) break;
698 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
699 i++; j = 0;
700 if (lpLogFontList[i] == NULL) break;
703 if (lpLogFontList[i] == NULL) break;
704 lpFaceList[j] = lpLogFontList[i]->lfFaceName;
705 dprintf_font(stddeb,"EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
707 else {
708 while(lpLogFontList[i] != NULL) {
709 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
710 i++;
712 if (lpLogFontList[i] == NULL) break;
714 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
715 hFont = CreateFontIndirect(lpLogFont);
716 hOldFont = SelectObject(hDC, hFont);
717 GetTextMetrics(hDC, lptm);
718 SelectObject(hDC, hOldFont);
719 DeleteObject(hFont);
720 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
722 #ifdef WINELIB
723 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
724 #else
725 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
726 2, (int)lptm, 0, (int)0, 2, (int)lpData);
727 #endif
728 if (nRet == 0) {
729 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
730 break;
733 USER_HEAP_FREE(hMet);
734 USER_HEAP_FREE(hLog);
735 return 0;
739 /*************************************************************************
740 * EnumFontFamilies [GDI.330]
742 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
744 HANDLE hLog;
745 HANDLE hMet;
746 HFONT hFont;
747 HFONT hOldFont;
748 LPLOGFONT lpLogFont;
749 LPTEXTMETRIC lptm;
750 LPSTR lpFaceList[MAX_FONTS];
751 char FaceName[LF_FACESIZE];
752 int nRet;
753 int j, i = 0;
755 dprintf_font(stddeb,"EnumFontFamilies(%04X, %08X, %08X, %08X)\n",
756 hDC, lpszFamily, lpEnumFunc, lpData);
757 if (lpEnumFunc == NULL) return 0;
758 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
759 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
760 if (lpLogFont == NULL) {
761 dprintf_font(stddeb,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
762 return 0;
764 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
765 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
766 if (lptm == NULL) {
767 USER_HEAP_FREE(hLog);
768 dprintf_font(stddeb,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
769 return 0;
771 if (lpszFamily != NULL) {
772 strcpy(FaceName, lpszFamily);
773 AnsiUpper(FaceName);
775 if (lpLogFontList[0] == NULL) InitFontsList();
776 memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
777 while (TRUE) {
778 if (lpLogFontList[i] == NULL) break;
779 if (lpszFamily == NULL) {
780 if (lpLogFontList[i] == NULL) break;
781 for (j = 0; j < MAX_FONTS; j++) {
782 if (lpFaceList[j] == NULL) break;
783 if (lpLogFontList[i] == NULL) break;
784 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
785 i++; j = 0;
788 if (lpLogFontList[i] == NULL) break;
789 lpFaceList[j] = lpLogFontList[i]->lfFaceName;
790 dprintf_font(stddeb,"EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
792 else {
793 while(lpLogFontList[i] != NULL) {
794 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
795 i++;
797 if (lpLogFontList[i] == NULL) break;
799 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
800 hFont = CreateFontIndirect(lpLogFont);
801 hOldFont = SelectObject(hDC, hFont);
802 GetTextMetrics(hDC, lptm);
803 SelectObject(hDC, hOldFont);
804 DeleteObject(hFont);
805 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
807 #ifdef WINELIB
808 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
809 #else
810 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
811 2, (int)lptm, 0, (int)0, 2, (int)lpData);
812 #endif
813 if (nRet == 0) {
814 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
815 break;
818 USER_HEAP_FREE(hMet);
819 USER_HEAP_FREE(hLog);
820 return 0;