Add registry entries for any fonts found by fontconfig or that are in
the FontDirs directories.
diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c
index feb8b79..36e198c 100644
--- a/dlls/gdi/freetype.c
+++ b/dlls/gdi/freetype.c
@@ -142,6 +142,7 @@
BOOL Bold;
FONTSIGNATURE fs;
FT_Fixed font_version;
+ BOOL external; /* TRUE if we should manually add this font to the registry */
struct tagFace *next;
struct tagFamily *family;
} Face;
@@ -195,6 +196,20 @@
static const WCHAR MSSansSerifW[] = {'M','S',' ','S','a','n','s',' ',
'S','e','r','i','f','\0'};
static const WCHAR HelvW[] = {'H','e','l','v','\0'};
+static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'};
+
+static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s','\\',
+ 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'F','o','n','t','s','\0'};
+
+static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s',' ','N','T','\\',
+ 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'F','o','n','t','s','\0'};
+
+static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','W','i','n','e','\\',
+ 'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
static const WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
static const WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
@@ -250,6 +265,12 @@
static FontSubst *substlist = NULL;
static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
+static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
+
+static inline BOOL is_win9x(void)
+{
+ return GetVersion() & 0x80000000;
+}
/*
This function builds an FT_Fixed from a float. It puts the integer part
in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
@@ -271,7 +292,7 @@
return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
}
-static BOOL AddFontFileToList(const char *file, char *fake_family)
+static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external_font)
{
FT_Face ft_face;
TT_OS2 *pOS2;
@@ -378,6 +399,7 @@
(*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
(*insertface)->font_version = pHeader->Font_Revision;
(*insertface)->family = family;
+ (*insertface)->external = external_font;
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
if(pOS2) {
@@ -602,7 +624,7 @@
TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
debugstr_w(face->StyleName), value);
/* Now add a new entry with the new family name */
- AddFontFileToList(face->file, value);
+ AddFontFileToList(face->file, value, face->external);
}
break;
}
@@ -618,7 +640,7 @@
}
-static BOOL ReadFontDir(const char *dirname)
+static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
{
DIR *dir;
struct dirent *dent;
@@ -647,9 +669,9 @@
continue;
}
if(S_ISDIR(statbuf.st_mode))
- ReadFontDir(path);
+ ReadFontDir(path, external_fonts);
else
- AddFontFileToList(path, NULL);
+ AddFontFileToList(path, NULL, external_fonts);
}
closedir(dir);
return TRUE;
@@ -707,7 +729,7 @@
if(len < 4) continue;
ext = v.u.s + len - 3;
if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf"))
- AddFontFileToList(v.u.s, NULL);
+ AddFontFileToList(v.u.s, NULL, TRUE);
}
pFcFontSetDestroy(fontset);
pFcObjectSetDestroy(os);
@@ -716,6 +738,111 @@
#endif
return;
}
+
+/*************************************************************
+ *
+ * This adds registry entries for any externally loaded fonts
+ * (fonts from fontconfig or FontDirs). It also deletes entries
+ * of no longer existing fonts.
+ *
+ */
+void update_reg_entries(void)
+{
+ HKEY winkey = 0, externalkey = 0;
+ LPWSTR valueW;
+ LPVOID data;
+ DWORD dlen, vlen, datalen, valuelen, i, type, len, len_fam;
+ Family *family;
+ Face *face;
+ WCHAR *file;
+ const WCHAR TrueType[] = {' ','(','T','r','u','e','T','y','p','e',')','\0'};
+ const WCHAR spaceW[] = {' ', '\0'};
+ char *path;
+
+ if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
+ 0, NULL, 0, KEY_ALL_ACCESS, NULL, &winkey, NULL) != ERROR_SUCCESS) {
+ ERR("Can't create Windows font reg key\n");
+ goto end;
+ }
+ if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, external_fonts_reg_key,
+ 0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
+ ERR("Can't create external font reg key\n");
+ goto end;
+ }
+
+ /* Delete all external fonts added last time */
+
+ RegQueryInfoKeyW(externalkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &valuelen, &datalen, NULL, NULL);
+ valuelen++; /* returned value doesn't include room for '\0' */
+ valueW = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(WCHAR));
+ data = HeapAlloc(GetProcessHeap(), 0, datalen * sizeof(WCHAR));
+
+ dlen = datalen * sizeof(WCHAR);
+ vlen = valuelen;
+ i = 0;
+ while(RegEnumValueW(externalkey, i++, valueW, &vlen, NULL, &type, data,
+ &dlen) == ERROR_SUCCESS) {
+
+ RegDeleteValueW(winkey, valueW);
+ /* reset dlen and vlen */
+ dlen = datalen;
+ vlen = valuelen;
+ }
+ HeapFree(GetProcessHeap(), 0, data);
+ HeapFree(GetProcessHeap(), 0, valueW);
+
+ /* Delete the old external fonts key */
+ RegCloseKey(externalkey);
+ externalkey = 0;
+ RegDeleteKeyW(HKEY_LOCAL_MACHINE, external_fonts_reg_key);
+
+ if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, external_fonts_reg_key,
+ 0, NULL, 0, KEY_ALL_ACCESS, NULL, &externalkey, NULL) != ERROR_SUCCESS) {
+ ERR("Can't create external font reg key\n");
+ goto end;
+ }
+
+ /* enumerate the fonts and add external ones to the two keys */
+
+ for(family = FontList; family; family = family->next) {
+ len_fam = strlenW(family->FamilyName) + sizeof(TrueType) / sizeof(WCHAR) + 1;
+ for(face = family->FirstFace; face; face = face->next) {
+ if(!face->external) continue;
+ len = len_fam;
+ if(strcmpiW(face->StyleName, RegularW))
+ len = len_fam + strlenW(face->StyleName) + 1;
+ valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ strcpyW(valueW, family->FamilyName);
+ if(len != len_fam) {
+ strcatW(valueW, spaceW);
+ strcatW(valueW, face->StyleName);
+ }
+ strcatW(valueW, TrueType);
+ if((path = strrchr(face->file, '/')) == NULL)
+ path = face->file;
+ else
+ path++;
+ len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
+
+ file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, path, -1, file, len);
+ RegSetValueExW(winkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
+ RegSetValueExW(externalkey, valueW, 0, REG_SZ, (BYTE*)file, len * sizeof(WCHAR));
+
+ HeapFree(GetProcessHeap(), 0, file);
+ HeapFree(GetProcessHeap(), 0, valueW);
+ }
+ }
+ end:
+ if(externalkey)
+ RegCloseKey(externalkey);
+ if(winkey)
+ RegCloseKey(winkey);
+ return;
+}
+
+
/*************************************************************
* WineEngAddFontResourceEx
*
@@ -730,7 +857,7 @@
FIXME("Ignoring flags %lx\n", flags);
if(wine_get_unix_file_name(file, unixname, sizeof(unixname)))
- AddFontFileToList(unixname, NULL);
+ AddFontFileToList(unixname, NULL, FALSE);
}
return 1;
}
@@ -758,6 +885,7 @@
LPVOID data;
WCHAR windowsdir[MAX_PATH];
char unixname[MAX_PATH];
+ HANDLE font_mutex;
TRACE("\n");
@@ -821,17 +949,23 @@
}
TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
+ if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
+ ERR("Failed to create font mutex\n");
+ return FALSE;
+ }
+ WaitForSingleObject(font_mutex, INFINITE);
+
/* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
strcatW(windowsdir, fontsW);
if(wine_get_unix_file_name(windowsdir, unixname, sizeof(unixname)))
- ReadFontDir(unixname);
+ ReadFontDir(unixname, FALSE);
- /* now look under HKLM\Software\Microsoft\Windows\CurrentVersion\Fonts
+ /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
for any fonts not installed in %WINDOWSDIR%\Fonts. They will have their
full path as the entry */
- if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Fonts",
+ if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
+ is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
&hkey) == ERROR_SUCCESS) {
LPWSTR valueW;
RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -847,7 +981,7 @@
&dlen) == ERROR_SUCCESS) {
if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
if(wine_get_unix_file_name((LPWSTR)data, unixname, sizeof(unixname)))
- AddFontFileToList(unixname, NULL);
+ AddFontFileToList(unixname, NULL, FALSE);
/* reset dlen and vlen */
dlen = datalen;
@@ -878,7 +1012,7 @@
while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
&dlen) == ERROR_SUCCESS) {
TRACE("Got %s=%s\n", value, (LPSTR)data);
- ReadFontDir((LPSTR)data);
+ ReadFontDir((LPSTR)data, TRUE);
/* reset dlen and vlen */
dlen = datalen;
vlen = valuelen;
@@ -892,6 +1026,9 @@
LoadSubstList();
DumpSubstList();
LoadReplaceList();
+ update_reg_entries();
+
+ ReleaseMutex(font_mutex);
return TRUE;
sym_not_found:
WINE_MESSAGE(