Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / FileManager / ViewSettings.cpp
1 // ViewSettings.h\r
2 \r
3 #include "StdAfx.h"\r
4  \r
5 #include "Common/IntToString.h"\r
6 #include "Common/StringConvert.h"\r
7 \r
8 #include "ViewSettings.h"\r
9 #include "Windows/Registry.h"\r
10 #include "Windows/Synchronization.h"\r
11 \r
12 using namespace NWindows;\r
13 using namespace NRegistry;\r
14 \r
15 #define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")\r
16 \r
17 static const TCHAR *kCUBasePath = REG_PATH_FM;\r
18 static const TCHAR *kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns");\r
19 \r
20 static const TCHAR *kPositionValueName = TEXT("Position");\r
21 static const TCHAR *kPanelsInfoValueName = TEXT("Panels");\r
22 static const TCHAR *kToolbars = TEXT("Toolbars");\r
23 \r
24 static const WCHAR *kPanelPathValueName = L"PanelPath";\r
25 static const TCHAR *kListMode = TEXT("ListMode");\r
26 static const TCHAR *kFolderHistoryValueName = TEXT("FolderHistory");\r
27 static const TCHAR *kFastFoldersValueName = TEXT("FolderShortcuts");\r
28 static const TCHAR *kCopyHistoryValueName = TEXT("CopyHistory");\r
29 \r
30 /*\r
31 class CColumnInfoSpec\r
32 {\r
33   UInt32 PropID;\r
34   Byte IsVisible;\r
35   UInt32 Width;\r
36 };\r
37 \r
38 struct CColumnHeader\r
39 {\r
40   UInt32 Version;\r
41   UInt32 SortID;\r
42   Byte Ascending;\r
43 };\r
44 */\r
45 \r
46 static const UInt32 kColumnInfoSpecHeader = 12;\r
47 static const UInt32 kColumnHeaderSize = 12;\r
48 \r
49 static const UInt32 kColumnInfoVersion = 1;\r
50 \r
51 static NSynchronization::CCriticalSection g_CS;\r
52 \r
53 class CTempOutBufferSpec\r
54 {\r
55   CByteBuffer Buffer;\r
56   UInt32 Size;\r
57   UInt32 Pos;\r
58 public:\r
59   operator const Byte *() const { return (const Byte *)Buffer; }\r
60   void Init(UInt32 dataSize)\r
61   {\r
62     Buffer.SetCapacity(dataSize);\r
63     Size = dataSize;\r
64     Pos = 0;\r
65   }\r
66   void WriteByte(Byte value)\r
67   {\r
68     if (Pos >= Size)\r
69       throw "overflow";\r
70     ((Byte *)Buffer)[Pos++] = value;\r
71   }\r
72   void WriteUInt32(UInt32 value)\r
73   {\r
74     for (int i = 0; i < 4; i++)\r
75     {\r
76       WriteByte((Byte)value);\r
77       value >>= 8;\r
78     }\r
79   }\r
80   void WriteBool(bool value)\r
81   {\r
82     WriteUInt32(value ? 1 : 0);\r
83   }\r
84 };\r
85 \r
86 class CTempInBufferSpec\r
87 {\r
88 public:\r
89   Byte *Buffer;\r
90   UInt32 Size;\r
91   UInt32 Pos;\r
92   Byte ReadByte()\r
93   {\r
94     if (Pos >= Size)\r
95       throw "overflow";\r
96     return Buffer[Pos++];\r
97   }\r
98   UInt32 ReadUInt32()\r
99   {\r
100     UInt32 value = 0;\r
101     for (int i = 0; i < 4; i++)\r
102       value |= (((UInt32)ReadByte()) << (8 * i));\r
103     return value;\r
104   }\r
105   bool ReadBool()\r
106   {\r
107     return (ReadUInt32() != 0);\r
108   }\r
109 };\r
110 \r
111 void SaveListViewInfo(const UString &id, const CListViewInfo &viewInfo)\r
112 {\r
113   const CObjectVector<CColumnInfo> &columns = viewInfo.Columns;\r
114   CTempOutBufferSpec buffer;\r
115   UInt32 dataSize = kColumnHeaderSize + kColumnInfoSpecHeader * columns.Size();\r
116   buffer.Init(dataSize);\r
117 \r
118   buffer.WriteUInt32(kColumnInfoVersion);\r
119   buffer.WriteUInt32(viewInfo.SortID);\r
120   buffer.WriteBool(viewInfo.Ascending);\r
121   for(int i = 0; i < columns.Size(); i++)\r
122   {\r
123     const CColumnInfo &column = columns[i];\r
124     buffer.WriteUInt32(column.PropID);\r
125     buffer.WriteBool(column.IsVisible);\r
126     buffer.WriteUInt32(column.Width);\r
127   }\r
128   {\r
129     NSynchronization::CCriticalSectionLock lock(g_CS);\r
130     CKey key;\r
131     key.Create(HKEY_CURRENT_USER, kCulumnsKeyName);\r
132     key.SetValue(GetSystemString(id), (const Byte *)buffer, dataSize);\r
133   }\r
134 }\r
135 \r
136 void ReadListViewInfo(const UString &id, CListViewInfo &viewInfo)\r
137 {\r
138   viewInfo.Clear();\r
139   CObjectVector<CColumnInfo> &columns = viewInfo.Columns;\r
140   CByteBuffer buffer;\r
141   UInt32 size;\r
142   {\r
143     NSynchronization::CCriticalSectionLock lock(g_CS);\r
144     CKey key;\r
145     if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS)\r
146       return;\r
147     if (key.QueryValue(GetSystemString(id), buffer, size) != ERROR_SUCCESS)\r
148       return;\r
149   }\r
150   if (size < kColumnHeaderSize)\r
151     return;\r
152   CTempInBufferSpec inBuffer;\r
153   inBuffer.Size = size;\r
154   inBuffer.Buffer = (Byte *)buffer;\r
155   inBuffer.Pos = 0;\r
156 \r
157 \r
158   UInt32 version = inBuffer.ReadUInt32();\r
159   if (version != kColumnInfoVersion)\r
160     return;\r
161   viewInfo.SortID = inBuffer.ReadUInt32();\r
162   viewInfo.Ascending = inBuffer.ReadBool();\r
163 \r
164   size -= kColumnHeaderSize;\r
165   if (size % kColumnInfoSpecHeader != 0)\r
166     return;\r
167   int numItems = size / kColumnInfoSpecHeader;\r
168   columns.Reserve(numItems);\r
169   for(int i = 0; i < numItems; i++)\r
170   {\r
171     CColumnInfo columnInfo;\r
172     columnInfo.PropID = inBuffer.ReadUInt32();\r
173     columnInfo.IsVisible = inBuffer.ReadBool();\r
174     columnInfo.Width = inBuffer.ReadUInt32();\r
175     columns.Add(columnInfo);\r
176   }\r
177 }\r
178 \r
179 static const UInt32 kWindowPositionHeaderSize = 5 * 4;\r
180 static const UInt32 kPanelsInfoHeaderSize = 3 * 4;\r
181 \r
182 /*\r
183 struct CWindowPosition\r
184 {\r
185   RECT Rect;\r
186   UInt32 Maximized;\r
187 };\r
188 \r
189 struct CPanelsInfo\r
190 {\r
191   UInt32 NumPanels;\r
192   UInt32 CurrentPanel;\r
193   UInt32 SplitterPos;\r
194 };\r
195 */\r
196 \r
197 void SaveWindowSize(const RECT &rect, bool maximized)\r
198 {\r
199   CSysString keyName = kCUBasePath;\r
200   NSynchronization::CCriticalSectionLock lock(g_CS);\r
201   CKey key;\r
202   key.Create(HKEY_CURRENT_USER, keyName);\r
203   // CWindowPosition position;\r
204   CTempOutBufferSpec buffer;\r
205   buffer.Init(kWindowPositionHeaderSize);\r
206   buffer.WriteUInt32(rect.left);\r
207   buffer.WriteUInt32(rect.top);\r
208   buffer.WriteUInt32(rect.right);\r
209   buffer.WriteUInt32(rect.bottom);\r
210   buffer.WriteBool(maximized);\r
211   key.SetValue(kPositionValueName, (const Byte *)buffer, kWindowPositionHeaderSize);\r
212 }\r
213 \r
214 bool ReadWindowSize(RECT &rect, bool &maximized)\r
215 {\r
216   CSysString keyName = kCUBasePath;\r
217   NSynchronization::CCriticalSectionLock lock(g_CS);\r
218   CKey key;\r
219   if (key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS)\r
220     return false;\r
221   CByteBuffer buffer;\r
222   UInt32 size;\r
223   if (key.QueryValue(kPositionValueName, buffer, size) != ERROR_SUCCESS)\r
224     return false;\r
225   if (size != kWindowPositionHeaderSize)\r
226     return false;\r
227   CTempInBufferSpec inBuffer;\r
228   inBuffer.Size = size;\r
229   inBuffer.Buffer = (Byte *)buffer;\r
230   inBuffer.Pos = 0;\r
231   rect.left = inBuffer.ReadUInt32();\r
232   rect.top = inBuffer.ReadUInt32();\r
233   rect.right = inBuffer.ReadUInt32();\r
234   rect.bottom = inBuffer.ReadUInt32();\r
235   maximized = inBuffer.ReadBool();\r
236   return true;\r
237 }\r
238 \r
239 void SavePanelsInfo(UInt32 numPanels, UInt32 currentPanel, UInt32 splitterPos)\r
240 {\r
241   CSysString keyName = kCUBasePath;\r
242   NSynchronization::CCriticalSectionLock lock(g_CS);\r
243   CKey key;\r
244   key.Create(HKEY_CURRENT_USER, keyName);\r
245 \r
246   CTempOutBufferSpec buffer;\r
247   buffer.Init(kPanelsInfoHeaderSize);\r
248   buffer.WriteUInt32(numPanels);\r
249   buffer.WriteUInt32(currentPanel);\r
250   buffer.WriteUInt32(splitterPos);\r
251   key.SetValue(kPanelsInfoValueName, (const Byte *)buffer, kPanelsInfoHeaderSize);\r
252 }\r
253 \r
254 bool ReadPanelsInfo(UInt32 &numPanels, UInt32 &currentPanel, UInt32 &splitterPos)\r
255 {\r
256   CSysString keyName = kCUBasePath;\r
257   NSynchronization::CCriticalSectionLock lock(g_CS);\r
258   CKey key;\r
259   if (key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS)\r
260     return false;\r
261   CByteBuffer buffer;\r
262   UInt32 size;\r
263   if (key.QueryValue(kPanelsInfoValueName, buffer, size) != ERROR_SUCCESS)\r
264     return false;\r
265   if (size != kPanelsInfoHeaderSize)\r
266     return false;\r
267   CTempInBufferSpec inBuffer;\r
268   inBuffer.Size = size;\r
269   inBuffer.Buffer = (Byte *)buffer;\r
270   inBuffer.Pos = 0;\r
271   numPanels = inBuffer.ReadUInt32();\r
272   currentPanel = inBuffer.ReadUInt32();\r
273   splitterPos = inBuffer.ReadUInt32();\r
274   return true;\r
275 }\r
276 \r
277 void SaveToolbarsMask(UInt32 toolbarMask)\r
278 {\r
279   CKey key;\r
280   key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
281   key.SetValue(kToolbars, toolbarMask);\r
282 }\r
283 \r
284 static const UInt32 kDefaultToolbarMask = ((UInt32)1 << 31) | 8 | 4 | 1;\r
285 \r
286 UInt32 ReadToolbarsMask()\r
287 {\r
288   CKey key;\r
289   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)\r
290     return kDefaultToolbarMask;\r
291   UInt32 mask;\r
292   if (key.QueryValue(kToolbars, mask) != ERROR_SUCCESS)\r
293     return kDefaultToolbarMask;\r
294   return mask;\r
295 }\r
296 \r
297 \r
298 static UString GetPanelPathName(UInt32 panelIndex)\r
299 {\r
300   WCHAR panelString[16];\r
301   ConvertUInt32ToString(panelIndex, panelString);\r
302   return UString(kPanelPathValueName) + panelString;\r
303 }\r
304 \r
305 \r
306 void SavePanelPath(UInt32 panel, const UString &path)\r
307 {\r
308   NSynchronization::CCriticalSectionLock lock(g_CS);\r
309   CKey key;\r
310   key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
311   key.SetValue(GetPanelPathName(panel), path);\r
312 }\r
313 \r
314 bool ReadPanelPath(UInt32 panel, UString &path)\r
315 {\r
316   NSynchronization::CCriticalSectionLock lock(g_CS);\r
317   CKey key;\r
318   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)\r
319     return false;\r
320   return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS);\r
321 }\r
322 \r
323 void SaveListMode(const CListMode &listMode)\r
324 {\r
325   CKey key;\r
326   key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
327   UInt32 t = 0;\r
328   for (int i = 0; i < 2; i++)\r
329     t |= ((listMode.Panels[i]) & 0xFF) << (i * 8);\r
330   key.SetValue(kListMode, t);\r
331 }\r
332 \r
333 void ReadListMode(CListMode &listMode)\r
334 {\r
335   CKey key;\r
336   listMode.Init();\r
337   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)\r
338     return;\r
339   UInt32 t;\r
340   if (key.QueryValue(kListMode, t) != ERROR_SUCCESS)\r
341     return;\r
342   for (int i = 0; i < 2; i++)\r
343   {\r
344     listMode.Panels[i] = (t & 0xFF);\r
345     t >>= 8;\r
346   }\r
347 }\r
348 \r
349 \r
350 static void SaveStringList(LPCTSTR valueName, const UStringVector &folders)\r
351 {\r
352   NSynchronization::CCriticalSectionLock lock(g_CS);\r
353   CKey key;\r
354   key.Create(HKEY_CURRENT_USER, kCUBasePath);\r
355   key.SetValue_Strings(valueName, folders);\r
356 }\r
357 \r
358 static void ReadStringList(LPCTSTR valueName, UStringVector &folders)\r
359 {\r
360   folders.Clear();\r
361   NSynchronization::CCriticalSectionLock lock(g_CS);\r
362   CKey key;\r
363   if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)\r
364     key.GetValue_Strings(valueName, folders);\r
365 }\r
366 \r
367 void SaveFolderHistory(const UStringVector &folders)\r
368   { SaveStringList(kFolderHistoryValueName, folders); }\r
369 void ReadFolderHistory(UStringVector &folders)\r
370   { ReadStringList(kFolderHistoryValueName, folders); }\r
371 \r
372 void SaveFastFolders(const UStringVector &folders)\r
373   { SaveStringList(kFastFoldersValueName, folders); }\r
374 void ReadFastFolders(UStringVector &folders)\r
375   { ReadStringList(kFastFoldersValueName, folders); }\r
376 \r
377 void SaveCopyHistory(const UStringVector &folders)\r
378   { SaveStringList(kCopyHistoryValueName, folders); }\r
379 void ReadCopyHistory(UStringVector &folders)\r
380   { ReadStringList(kCopyHistoryValueName, folders); }\r
381 \r
382 void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s)\r
383 {\r
384   for (int i = 0; i < list.Size();)\r
385     if (s.CompareNoCase(list[i]) == 0)\r
386       list.Delete(i);\r
387     else\r
388       i++;\r
389   list.Insert(0, s);\r
390 }\r