[FONTEXT] Add detail view columns to font folder
[reactos.git] / dll / shellext / fontext / CFontCache.cpp
1 /*
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)
6 */
7
8 #include "precomp.h"
9
10 WINE_DEFAULT_DEBUG_CHANNEL(fontext);
11
12 CFontCache* g_FontCache = NULL;
13
14 CFontInfo::CFontInfo(LPCWSTR name)
15 : m_Name(name)
16 , m_FileRead(false)
17 {
18 }
19
20 const CStringW& CFontInfo::Name() const
21 {
22 return m_Name;
23 }
24
25 const bool CFontInfo::Valid() const
26 {
27 return !m_Name.IsEmpty();
28 }
29
30 const CStringW& CFontInfo::File()
31 {
32 if (!m_FileRead)
33 {
34 if (Valid())
35 {
36 // Read the filename stored in the registry.
37 // This can be either a filename or a full path
38 CRegKey key;
39 if (key.Open(FONT_HIVE, FONT_KEY, KEY_READ) == ERROR_SUCCESS)
40 {
41 CStringW Value;
42 DWORD dwAllocated = 128;
43 LSTATUS Status;
44 do
45 {
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)
51 {
52 // Ensure we do not re-use the same string object, by passing it a PCWSTR
53 m_File = Value.GetString();
54 break;
55 }
56 dwAllocated += 128;
57 } while (Status == ERROR_MORE_DATA);
58 }
59 }
60 m_FileRead = true;
61 }
62 return m_File;
63 }
64
65
66
67 CFontCache::CFontCache()
68 {
69 }
70
71 void CFontCache::SetFontDir(const LPCWSTR Path)
72 {
73 if (m_FontFolderPath.IsEmpty())
74 m_FontFolderPath = Path;
75 }
76
77 size_t CFontCache::Size()
78 {
79 if (m_Fonts.GetCount() == 0u)
80 Read();
81
82 return m_Fonts.GetCount();
83 }
84
85 CStringW CFontCache::Name(size_t Index)
86 {
87 if (m_Fonts.GetCount() == 0u)
88 Read();
89
90 if (Index >= m_Fonts.GetCount())
91 return CStringW();
92
93 return m_Fonts[Index].Name();
94 }
95
96 CStringW CFontCache::Filename(const FontPidlEntry* fontEntry, bool alwaysFullPath)
97 {
98 CStringW File;
99
100 if (fontEntry->Index < m_Fonts.GetCount())
101 {
102 CFontInfo& info = m_Fonts[fontEntry->Index];
103
104 if (info.Name().CompareNoCase(fontEntry->Name) == 0)
105 File = info.File();
106 }
107
108 for (UINT n = 0; File.IsEmpty() && n < Size(); ++n)
109 {
110 if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
111 File = m_Fonts[n].File();
112 }
113
114 if (!File.IsEmpty() && alwaysFullPath)
115 {
116 // Ensure this is a full path
117 if (PathIsRelativeW(File))
118 {
119 File = m_FontFolderPath + File;
120 }
121 }
122
123 return File;
124 }
125
126 void CFontCache::Insert(CAtlList<CFontInfo>& fonts, const CStringW& KeyName)
127 {
128 POSITION it = fonts.GetHeadPosition();
129 while (it != NULL)
130 {
131 POSITION lastit = it;
132 const CFontInfo& info = fonts.GetNext(it);
133 if (info.Name().CompareNoCase(KeyName) >= 0)
134 {
135 fonts.InsertBefore(lastit, CFontInfo(KeyName));
136 return;
137 }
138 }
139 fonts.AddTail(CFontInfo(KeyName));
140 }
141
142 void CFontCache::Read()
143 {
144 CAtlList<CFontInfo> fonts;
145 CRegKey key;
146
147 // Enumerate all registered font names
148 if (key.Open(FONT_HIVE, FONT_KEY, KEY_READ) == ERROR_SUCCESS)
149 {
150 LSTATUS Status;
151 DWORD dwAllocated = 128;
152 DWORD ilIndex = 0;
153 CStringW KeyName;
154 do
155 {
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)
161 {
162 // Insert will create an ordered list
163 Insert(fonts, KeyName);
164 ilIndex++;
165 continue;
166 }
167 if (Status == ERROR_NO_MORE_ITEMS)
168 break;
169 else if (Status == ERROR_MORE_DATA)
170 {
171 dwAllocated += 128;
172 }
173 } while (Status == ERROR_MORE_DATA || Status == ERROR_SUCCESS);
174 }
175
176 // Move the fonts from a list to an array (for easy indexing)
177 m_Fonts.SetCount(fonts.GetCount());
178 size_t Index = 0;
179 POSITION it = fonts.GetHeadPosition();
180 while (it != NULL)
181 {
182 m_Fonts[Index] = fonts.GetNext(it);
183 Index++;
184 }
185 }
186