fonts: add registry entries for 'external' fonts

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Mar 8 05:54:23 CST 2004


        Huw Davies <huw at codeweavers.com>
        Add registry entries for any fonts found by fontconfig or that
        are in the FontDirs directories.
-- 
Huw Davies
huw at codeweavers.com
Index: freetype.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/freetype.c,v
retrieving revision 1.55
diff -u -r1.55 freetype.c
--- freetype.c	12 Feb 2004 20:05:47 -0000	1.55
+++ freetype.c	8 Mar 2004 11:49:45 -0000
@@ -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(



More information about the wine-patches mailing list