+import "AVLTree"
+
+public struct FontInfo
+{
+ bool fixedPitch;
+ bool defaultOrAnsiCharSet;
+};
+
+#if defined(__WIN32__)
+static int CALLBACK fontLister(ENUMLOGFONTEXW * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
+{
+ // const String faceName = font->elfLogFont.lfFaceName;
+ uint16 * faceName = font->elfLogFont.lfFaceName;
+ String s = UTF16toUTF8(faceName);
+ if(s[0] != '@')
+ {
+ Map<String, FontInfo> fonts = (Map<String, FontInfo>)lParam;
+ MapIterator<String, FontInfo> it { map = fonts };
+ if(!it.Index(s, true))
+ it.data = { (font->elfLogFont.lfPitchAndFamily & 3) == FIXED_PITCH, defaultOrAnsiCharSet = (font->elfLogFont.lfCharSet == ANSI_CHARSET || font->elfLogFont.lfCharSet == DEFAULT_CHARSET) };
+ }
+ delete s;
+ return 1;
+}
+#endif
+
+public Map<String, FontInfo> ListAvailableFonts()
+{
+ Map<String, FontInfo> fonts { };
+
+#if defined(__WIN32__)
+ LOGFONTW logFont = { 0 };
+ HDC hdc = GetDC(0);
+ logFont.lfCharSet = DEFAULT_CHARSET;
+
+ EnumFontFamiliesExW(hdc, &logFont, (void *)fontLister, (LPARAM)fonts, 0);
+
+ ReleaseDC(0, hdc);
+#elif !defined(ECERE_NOFONTCONFIG)
+ int i;
+ FcPattern * pattern;
+ FcObjectSet * objectSet;
+ FcFontSet * fontSet;
+
+ if(!fcConfig)
+ fcConfig = FcInitLoadConfigAndFonts();
+
+ pattern = FcPatternCreate();
+ objectSet = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_CHARSET, null);
+ fontSet = FcFontList(fcConfig, pattern, objectSet);
+ if(fontSet)
+ {
+ MapIterator<String, FontInfo> it { map = fonts };
+ for(i = 0; i < fontSet->nfont; i++)
+ {
+ FcPattern * font = fontSet->fonts[i];
+ String family;
+ int spacing;
+ FcCharSet * charSet;
+
+ if(FcPatternGetString(font, FC_FAMILY, 0, (byte **)&family) == FcResultMatch &&
+ FcPatternGetInteger(font, FC_SPACING, 0, &spacing) == FcResultMatch &&
+ FcPatternGetCharSet(font, FC_CHARSET, 0, &charSet) == FcResultMatch)
+ {
+ if(!it.Index(family, true))
+ {
+ it.data =
+ {
+ fixedPitch = spacing == FC_MONO,
+ defaultOrAnsiCharSet =
+ FcCharSetHasChar(charSet, '[') && FcCharSetHasChar(charSet, '{') &&
+ FcCharSetHasChar(charSet, 'a') && FcCharSetHasChar(charSet, 'Z');
+ };
+ }
+ }
+ }
+ }
+ if(pattern) FcPatternDestroy(pattern);
+ if(fontSet) FcFontSetDestroy(fontSet);
+#endif
+ return fonts;
+}
+