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 Mark Jansen (mark.jansen@reactos.org)
10 WINE_DEFAULT_DEBUG_CHANNEL(fontext
);
13 #define FONT_HIVE HKEY_LOCAL_MACHINE
14 #define FONT_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
16 CFontCache
* g_FontCache
= NULL
;
18 CFontInfo::CFontInfo(LPCWSTR name
)
24 const CStringW
& CFontInfo::Name() const
29 const bool CFontInfo::Valid() const
31 return !m_Name
.IsEmpty();
34 const CStringW
& CFontInfo::File()
40 // Read the filename stored in the registry.
41 // This can be either a filename or a full path
43 if (key
.Open(FONT_HIVE
, FONT_KEY
, KEY_READ
) == ERROR_SUCCESS
)
46 DWORD dwAllocated
= 128;
50 DWORD dwSize
= dwAllocated
;
51 PWSTR Buffer
= Value
.GetBuffer(dwSize
);
52 Status
= key
.QueryStringValue(m_Name
, Buffer
, &dwSize
);
53 Value
.ReleaseBuffer(dwSize
);
54 if (Status
== ERROR_SUCCESS
)
56 // Ensure we do not re-use the same string object, by passing it a PCWSTR
57 m_File
= Value
.GetString();
61 } while (Status
== ERROR_MORE_DATA
);
71 CFontCache::CFontCache()
75 size_t CFontCache::Size()
77 if (m_Fonts
.GetCount() == 0u)
80 return m_Fonts
.GetCount();
83 CStringW
CFontCache::Name(size_t Index
)
85 if (m_Fonts
.GetCount() == 0u)
88 if (Index
>= m_Fonts
.GetCount())
91 return m_Fonts
[Index
].Name();
94 CStringW
CFontCache::Filename(const FontPidlEntry
* fontEntry
)
96 if (fontEntry
->Index
< m_Fonts
.GetCount())
98 CFontInfo
& info
= m_Fonts
[fontEntry
->Index
];
100 if (info
.Name().CompareNoCase(fontEntry
->Name
) == 0)
104 for (UINT n
= 0; n
< Size(); ++n
)
106 if (m_Fonts
[n
].Name().CompareNoCase(fontEntry
->Name
) == 0)
107 return m_Fonts
[n
].File();
113 void CFontCache::Insert(CAtlList
<CFontInfo
>& fonts
, const CStringW
& KeyName
)
115 POSITION it
= fonts
.GetHeadPosition();
118 POSITION lastit
= it
;
119 const CFontInfo
& info
= fonts
.GetNext(it
);
120 if (info
.Name().CompareNoCase(KeyName
) >= 0)
122 fonts
.InsertBefore(lastit
, CFontInfo(KeyName
));
126 fonts
.AddTail(CFontInfo(KeyName
));
129 void CFontCache::Read()
131 CAtlList
<CFontInfo
> fonts
;
134 // Enumerate all registered font names
135 if (key
.Open(FONT_HIVE
, FONT_KEY
, KEY_READ
) == ERROR_SUCCESS
)
138 DWORD dwAllocated
= 128;
143 DWORD dwSize
= dwAllocated
;
144 PWSTR Buffer
= KeyName
.GetBuffer(dwSize
);
145 Status
= RegEnumValueW(key
.m_hKey
, ilIndex
, Buffer
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
146 KeyName
.ReleaseBuffer(dwSize
);
147 if (Status
== ERROR_SUCCESS
)
149 // Insert will create an ordered list
150 Insert(fonts
, KeyName
);
154 if (Status
== ERROR_NO_MORE_ITEMS
)
156 else if (Status
== ERROR_MORE_DATA
)
160 } while (Status
== ERROR_MORE_DATA
|| Status
== ERROR_SUCCESS
);
163 // Move the fonts from a list to an array (for easy indexing)
164 m_Fonts
.SetCount(fonts
.GetCount());
166 POSITION it
= fonts
.GetHeadPosition();
169 m_Fonts
[Index
] = fonts
.GetNext(it
);