1 // ViewSettings.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../../C/CpuArch.h"
6 
7 #include "../../../Common/IntToString.h"
8 #include "../../../Common/StringConvert.h"
9 
10 #include "../../../Windows/Registry.h"
11 #include "../../../Windows/Synchronization.h"
12 
13 #include "ViewSettings.h"
14 
15 using namespace NWindows;
16 using namespace NRegistry;
17 
18 #define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")
19 
20 static LPCTSTR const kCUBasePath = REG_PATH_FM;
21 static LPCTSTR const kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns");
22 
23 static LPCTSTR const kPositionValueName = TEXT("Position");
24 static LPCTSTR const kPanelsInfoValueName = TEXT("Panels");
25 static LPCTSTR const kToolbars = TEXT("Toolbars");
26 
27 static LPCWSTR const kPanelPathValueName = L"PanelPath";
28 
29 static LPCTSTR const kListMode = TEXT("ListMode");
30 static LPCTSTR const kFolderHistoryValueName = TEXT("FolderHistory");
31 static LPCTSTR const kFastFoldersValueName = TEXT("FolderShortcuts");
32 static LPCTSTR const kCopyHistoryValueName = TEXT("CopyHistory");
33 
34 static NSynchronization::CCriticalSection g_CS;
35 
36 #define Set32(p, v) SetUi32(((Byte *)p), v)
37 #define SetBool(p, v) Set32(p, ((v) ? 1 : 0))
38 
39 #define Get32(p, dest) dest = GetUi32((const Byte *)p)
40 #define GetBool(p, dest) dest = (GetUi32(p) != 0);
41 
42 /*
43 struct CColumnHeader
44 {
45   UInt32 Version;
46   UInt32 SortID;
47   UInt32 Ascending; // bool
48 };
49 */
50 
51 static const UInt32 kListViewHeaderSize = 3 * 4;
52 static const UInt32 kColumnInfoSize = 3 * 4;
53 static const UInt32 kListViewVersion = 1;
54 
Save(const UString & id) const55 void CListViewInfo::Save(const UString &id) const
56 {
57   const UInt32 dataSize = kListViewHeaderSize + kColumnInfoSize * Columns.Size();
58   CByteArr buf(dataSize);
59 
60   Set32(buf, kListViewVersion);
61   Set32(buf + 4, SortID);
62   SetBool(buf + 8, Ascending);
63   FOR_VECTOR (i, Columns)
64   {
65     const CColumnInfo &column = Columns[i];
66     Byte *p = buf + kListViewHeaderSize + i * kColumnInfoSize;
67     Set32(p, column.PropID);
68     SetBool(p + 4, column.IsVisible);
69     Set32(p + 8, column.Width);
70   }
71   {
72     NSynchronization::CCriticalSectionLock lock(g_CS);
73     CKey key;
74     key.Create(HKEY_CURRENT_USER, kCulumnsKeyName);
75     key.SetValue(GetSystemString(id), (const Byte *)buf, dataSize);
76   }
77 }
78 
Read(const UString & id)79 void CListViewInfo::Read(const UString &id)
80 {
81   Clear();
82   CByteBuffer buf;
83   UInt32 size;
84   {
85     NSynchronization::CCriticalSectionLock lock(g_CS);
86     CKey key;
87     if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS)
88       return;
89     if (key.QueryValue(GetSystemString(id), buf, size) != ERROR_SUCCESS)
90       return;
91   }
92   if (size < kListViewHeaderSize)
93     return;
94   UInt32 version;
95   Get32(buf, version);
96   if (version != kListViewVersion)
97     return;
98   Get32(buf + 4, SortID);
99   GetBool(buf + 8, Ascending);
100 
101   IsLoaded = true;
102 
103   size -= kListViewHeaderSize;
104   if (size % kColumnInfoSize != 0)
105     return;
106   unsigned numItems = size / kColumnInfoSize;
107   Columns.ClearAndReserve(numItems);
108   for (unsigned i = 0; i < numItems; i++)
109   {
110     CColumnInfo column;
111     const Byte *p = buf + kListViewHeaderSize + i * kColumnInfoSize;
112     Get32(p, column.PropID);
113     GetBool(p + 4, column.IsVisible);
114     Get32(p + 8, column.Width);
115     Columns.AddInReserved(column);
116   }
117 }
118 
119 
120 /*
121 struct CWindowPosition
122 {
123   RECT Rect;
124   UInt32 Maximized; // bool
125 };
126 
127 struct CPanelsInfo
128 {
129   UInt32 NumPanels;
130   UInt32 CurrentPanel;
131   UInt32 SplitterPos;
132 };
133 */
134 
135 static const UInt32 kWindowPositionHeaderSize = 5 * 4;
136 static const UInt32 kPanelsInfoHeaderSize = 3 * 4;
137 
Save() const138 void CWindowInfo::Save() const
139 {
140   NSynchronization::CCriticalSectionLock lock(g_CS);
141   CKey key;
142   key.Create(HKEY_CURRENT_USER, kCUBasePath);
143   {
144     Byte buf[kWindowPositionHeaderSize];
145     Set32(buf,      rect.left);
146     Set32(buf +  4, rect.top);
147     Set32(buf +  8, rect.right);
148     Set32(buf + 12, rect.bottom);
149     SetBool(buf + 16, maximized);
150     key.SetValue(kPositionValueName, buf, kWindowPositionHeaderSize);
151   }
152   {
153     Byte buf[kPanelsInfoHeaderSize];
154     Set32(buf,      numPanels);
155     Set32(buf +  4, currentPanel);
156     Set32(buf +  8, splitterPos);
157     key.SetValue(kPanelsInfoValueName, buf, kPanelsInfoHeaderSize);
158   }
159 }
160 
QueryBuf(CKey & key,LPCTSTR name,CByteBuffer & buf,UInt32 dataSize)161 static bool QueryBuf(CKey &key, LPCTSTR name, CByteBuffer &buf, UInt32 dataSize)
162 {
163   UInt32 size;
164   return key.QueryValue(name, buf, size) == ERROR_SUCCESS && size == dataSize;
165 }
166 
Read(bool & windowPosDefined,bool & panelInfoDefined)167 void CWindowInfo::Read(bool &windowPosDefined, bool &panelInfoDefined)
168 {
169   windowPosDefined = false;
170   panelInfoDefined = false;
171   NSynchronization::CCriticalSectionLock lock(g_CS);
172   CKey key;
173   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)
174     return;
175   CByteBuffer buf;
176   if (QueryBuf(key, kPositionValueName, buf, kWindowPositionHeaderSize))
177   {
178     Get32(buf,      rect.left);
179     Get32(buf +  4, rect.top);
180     Get32(buf +  8, rect.right);
181     Get32(buf + 12, rect.bottom);
182     GetBool(buf + 16, maximized);
183     windowPosDefined = true;
184   }
185   if (QueryBuf(key, kPanelsInfoValueName, buf, kPanelsInfoHeaderSize))
186   {
187     Get32(buf,      numPanels);
188     Get32(buf +  4, currentPanel);
189     Get32(buf +  8, splitterPos);
190     panelInfoDefined = true;
191   }
192   return;
193 }
194 
195 
SaveUi32Val(const TCHAR * name,UInt32 value)196 static void SaveUi32Val(const TCHAR *name, UInt32 value)
197 {
198   CKey key;
199   key.Create(HKEY_CURRENT_USER, kCUBasePath);
200   key.SetValue(name, value);
201 }
202 
ReadUi32Val(const TCHAR * name,UInt32 & value)203 static bool ReadUi32Val(const TCHAR *name, UInt32 &value)
204 {
205   CKey key;
206   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)
207     return false;
208   return key.QueryValue(name, value) == ERROR_SUCCESS;
209 }
210 
SaveToolbarsMask(UInt32 toolbarMask)211 void SaveToolbarsMask(UInt32 toolbarMask)
212 {
213   SaveUi32Val(kToolbars, toolbarMask);
214 }
215 
216 static const UInt32 kDefaultToolbarMask = ((UInt32)1 << 31) | 8 | 4 | 1;
217 
ReadToolbarsMask()218 UInt32 ReadToolbarsMask()
219 {
220   UInt32 mask;
221   if (!ReadUi32Val(kToolbars, mask))
222     return kDefaultToolbarMask;
223   return mask;
224 }
225 
226 
Save() const227 void CListMode::Save() const
228 {
229   UInt32 t = 0;
230   for (int i = 0; i < 2; i++)
231     t |= ((Panels[i]) & 0xFF) << (i * 8);
232   SaveUi32Val(kListMode, t);
233 }
234 
Read()235 void CListMode::Read()
236 {
237   Init();
238   UInt32 t;
239   if (!ReadUi32Val(kListMode, t))
240     return;
241   for (int i = 0; i < 2; i++)
242   {
243     Panels[i] = (t & 0xFF);
244     t >>= 8;
245   }
246 }
247 
GetPanelPathName(UInt32 panelIndex)248 static UString GetPanelPathName(UInt32 panelIndex)
249 {
250   UString s (kPanelPathValueName);
251   s.Add_UInt32(panelIndex);
252   return s;
253 }
254 
SavePanelPath(UInt32 panel,const UString & path)255 void SavePanelPath(UInt32 panel, const UString &path)
256 {
257   NSynchronization::CCriticalSectionLock lock(g_CS);
258   CKey key;
259   key.Create(HKEY_CURRENT_USER, kCUBasePath);
260   key.SetValue(GetPanelPathName(panel), path);
261 }
262 
ReadPanelPath(UInt32 panel,UString & path)263 bool ReadPanelPath(UInt32 panel, UString &path)
264 {
265   NSynchronization::CCriticalSectionLock lock(g_CS);
266   CKey key;
267   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)
268     return false;
269   return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS);
270 }
271 
272 
SaveStringList(LPCTSTR valueName,const UStringVector & folders)273 static void SaveStringList(LPCTSTR valueName, const UStringVector &folders)
274 {
275   NSynchronization::CCriticalSectionLock lock(g_CS);
276   CKey key;
277   key.Create(HKEY_CURRENT_USER, kCUBasePath);
278   key.SetValue_Strings(valueName, folders);
279 }
280 
ReadStringList(LPCTSTR valueName,UStringVector & folders)281 static void ReadStringList(LPCTSTR valueName, UStringVector &folders)
282 {
283   folders.Clear();
284   NSynchronization::CCriticalSectionLock lock(g_CS);
285   CKey key;
286   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)
287     key.GetValue_Strings(valueName, folders);
288 }
289 
SaveFolderHistory(const UStringVector & folders)290 void SaveFolderHistory(const UStringVector &folders)
291   { SaveStringList(kFolderHistoryValueName, folders); }
ReadFolderHistory(UStringVector & folders)292 void ReadFolderHistory(UStringVector &folders)
293   { ReadStringList(kFolderHistoryValueName, folders); }
294 
SaveFastFolders(const UStringVector & folders)295 void SaveFastFolders(const UStringVector &folders)
296   { SaveStringList(kFastFoldersValueName, folders); }
ReadFastFolders(UStringVector & folders)297 void ReadFastFolders(UStringVector &folders)
298   { ReadStringList(kFastFoldersValueName, folders); }
299 
SaveCopyHistory(const UStringVector & folders)300 void SaveCopyHistory(const UStringVector &folders)
301   { SaveStringList(kCopyHistoryValueName, folders); }
ReadCopyHistory(UStringVector & folders)302 void ReadCopyHistory(UStringVector &folders)
303   { ReadStringList(kCopyHistoryValueName, folders); }
304 
AddUniqueStringToHeadOfList(UStringVector & list,const UString & s)305 void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s)
306 {
307   for (unsigned i = 0; i < list.Size();)
308     if (s.IsEqualTo_NoCase(list[i]))
309       list.Delete(i);
310     else
311       i++;
312   list.Insert(0, s);
313 }
314