2 * PROJECT: ReactOS Font Shell Extension
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: font list cache handling
5 * COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
10 WINE_DEFAULT_DEBUG_CHANNEL(fontext
);
12 CFontCache
* g_FontCache
= NULL
;
14 CFontInfo::CFontInfo(LPCWSTR name
)
20 const CStringW
& CFontInfo::Name() const
25 const bool CFontInfo::Valid() const
27 return !m_Name
.IsEmpty();
30 const CStringW
& CFontInfo::File()
36 // Read the filename stored in the registry.
37 // This can be either a filename or a full path
39 if (key
.Open(FONT_HIVE
, FONT_KEY
, KEY_READ
) == ERROR_SUCCESS
)
42 DWORD dwAllocated
= 128;
46 DWORD dwSize
= dwAllocated
;
47 PWSTR Buffer
= Value
.GetBuffer(dwSize
);
48 Status
= key
.QueryStringValue(m_Name
, Buffer
, &dwSize
);
49 Value
.ReleaseBuffer(dwSize
);
50 if (Status
== ERROR_SUCCESS
)
52 // Ensure we do not re-use the same string object, by passing it a PCWSTR
53 m_File
= Value
.GetString();
57 } while (Status
== ERROR_MORE_DATA
);
67 CFontCache::CFontCache()
71 void CFontCache::SetFontDir(const LPCWSTR Path
)
73 if (m_FontFolderPath
.IsEmpty())
74 m_FontFolderPath
= Path
;
77 size_t CFontCache::Size()
79 if (m_Fonts
.GetCount() == 0u)
82 return m_Fonts
.GetCount();
85 CStringW
CFontCache::Name(size_t Index
)
87 if (m_Fonts
.GetCount() == 0u)
90 if (Index
>= m_Fonts
.GetCount())
93 return m_Fonts
[Index
].Name();
96 CStringW
CFontCache::Filename(const FontPidlEntry
* fontEntry
, bool alwaysFullPath
)
100 if (fontEntry
->Index
< m_Fonts
.GetCount())
102 CFontInfo
& info
= m_Fonts
[fontEntry
->Index
];
104 if (info
.Name().CompareNoCase(fontEntry
->Name
) == 0)
108 for (UINT n
= 0; File
.IsEmpty() && n
< Size(); ++n
)
110 if (m_Fonts
[n
].Name().CompareNoCase(fontEntry
->Name
) == 0)
111 File
= m_Fonts
[n
].File();
114 if (!File
.IsEmpty() && alwaysFullPath
)
116 // Ensure this is a full path
117 if (PathIsRelativeW(File
))
119 File
= m_FontFolderPath
+ File
;
126 void CFontCache::Insert(CAtlList
<CFontInfo
>& fonts
, const CStringW
& KeyName
)
128 POSITION it
= fonts
.GetHeadPosition();
131 POSITION lastit
= it
;
132 const CFontInfo
& info
= fonts
.GetNext(it
);
133 if (info
.Name().CompareNoCase(KeyName
) >= 0)
135 fonts
.InsertBefore(lastit
, CFontInfo(KeyName
));
139 fonts
.AddTail(CFontInfo(KeyName
));
142 void CFontCache::Read()
144 CAtlList
<CFontInfo
> fonts
;
147 // Enumerate all registered font names
148 if (key
.Open(FONT_HIVE
, FONT_KEY
, KEY_READ
) == ERROR_SUCCESS
)
151 DWORD dwAllocated
= 128;
156 DWORD dwSize
= dwAllocated
;
157 PWSTR Buffer
= KeyName
.GetBuffer(dwSize
);
158 Status
= RegEnumValueW(key
.m_hKey
, ilIndex
, Buffer
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
159 KeyName
.ReleaseBuffer(dwSize
);
160 if (Status
== ERROR_SUCCESS
)
162 // Insert will create an ordered list
163 Insert(fonts
, KeyName
);
167 if (Status
== ERROR_NO_MORE_ITEMS
)
169 else if (Status
== ERROR_MORE_DATA
)
173 } while (Status
== ERROR_MORE_DATA
|| Status
== ERROR_SUCCESS
);
176 // Move the fonts from a list to an array (for easy indexing)
177 m_Fonts
.SetCount(fonts
.GetCount());
179 POSITION it
= fonts
.GetHeadPosition();
182 m_Fonts
[Index
] = fonts
.GetNext(it
);