// ViewSettings.h #include "StdAfx.h" #include "Common/IntToString.h" #include "ViewSettings.h" #include "Windows/Registry.h" #include "Windows/Synchronization.h" using namespace NWindows; using namespace NRegistry; static const TCHAR *kCUBasePath = TEXT("Software\\7-Zip\\FM"); static const TCHAR *kCulumnsKeyName = TEXT("Columns"); static const TCHAR *kPositionValueName = TEXT("Position"); static const TCHAR *kPanelsInfoValueName = TEXT("Panels"); static const TCHAR *kToolbars = TEXT("Toolbars"); static const TCHAR *kPanelPathValueName = TEXT("PanelPath"); static const TCHAR *kFolderHistoryValueName = TEXT("FolderHistory"); static const TCHAR *kFastFoldersValueName = TEXT("FolderShortcuts"); static const TCHAR *kCopyHistoryValueName = TEXT("CopyHistory"); #pragma pack( push, PragmaColumnInfoSpec) #pragma pack( push, 1) class CColumnInfoSpec { UINT32 PropID; BYTE IsVisible; UINT32 Width; public: void GetFromColumnInfo(const CColumnInfo &aSrc) { PropID = aSrc.PropID; IsVisible = aSrc.IsVisible ? 1: 0; Width = aSrc.Width; } void PutColumnInfo(CColumnInfo &aDest) { aDest.PropID = PropID; aDest.IsVisible = (IsVisible != 0); aDest.Width = Width; } }; struct CColumnHeader { UINT32 Version; // UINT32 SortIndex; UINT32 SortID; BYTE Ascending; }; #pragma pack(pop) #pragma pack(pop, PragmaColumnInfoSpec) static const UINT32 kColumnInfoVersion = 0; static NSynchronization::CCriticalSection g_RegistryOperationsCriticalSection; void SaveListViewInfo(const CSysString &id, const CListViewInfo &viewInfo) { const CObjectVector &columns = viewInfo.Columns; CByteBuffer buffer; UINT32 dataSize = sizeof(CColumnHeader) + sizeof(CColumnInfoSpec) * columns.Size(); buffer.SetCapacity(dataSize); BYTE *dataPointer = (BYTE *)buffer; CColumnHeader &columnHeader = *(CColumnHeader *)dataPointer; columnHeader.Version = kColumnInfoVersion; // columnHeader.SortIndex = viewInfo.SortIndex; columnHeader.SortID = viewInfo.SortID; columnHeader.Ascending = viewInfo.Ascending ? 1 : 0; CColumnInfoSpec *destItems = (CColumnInfoSpec *)(dataPointer + sizeof(CColumnHeader)); for(int i = 0; i < columns.Size(); i++) { CColumnInfoSpec &columnInfoSpec = destItems[i]; columnInfoSpec.GetFromColumnInfo(columns[i]); } { NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); CSysString keyName = kCUBasePath; keyName += kKeyNameDelimiter; keyName += kCulumnsKeyName; CKey key; key.Create(HKEY_CURRENT_USER, keyName); key.SetValue(id, dataPointer, dataSize); } } void ReadListViewInfo(const CSysString &id, CListViewInfo &viewInfo) { viewInfo.Clear(); CObjectVector &columns = viewInfo.Columns; CByteBuffer buffer; UINT32 size; { NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); CSysString keyName = kCUBasePath; keyName += kKeyNameDelimiter; keyName += kCulumnsKeyName; CKey key; if(key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS) return; if (key.QueryValue(id, buffer, size) != ERROR_SUCCESS) return; } if (size < sizeof(CColumnHeader)) return; BYTE *dataPointer = (BYTE *)buffer; const CColumnHeader &columnHeader = *(CColumnHeader*)dataPointer; if (columnHeader.Version != kColumnInfoVersion) return; viewInfo.Ascending = (columnHeader.Ascending != 0); // viewInfo.SortIndex = columnHeader.SortIndex; viewInfo.SortID = columnHeader.SortID; size -= sizeof(CColumnHeader); if (size % sizeof(CColumnHeader) != 0) return; int numItems = size / sizeof(CColumnInfoSpec); CColumnInfoSpec *specItems = (CColumnInfoSpec *)(dataPointer + sizeof(CColumnHeader));; columns.Reserve(numItems); for(int i = 0; i < numItems; i++) { CColumnInfo columnInfo; specItems[i].PutColumnInfo(columnInfo); columns.Add(columnInfo); } } #pragma pack( push, PragmaWindowPosition) #pragma pack( push, 1) struct CWindowPosition { RECT Rect; UINT32 Maximized; }; struct CPanelsInfo { UINT32 NumPanels; UINT32 CurrentPanel; UINT32 SplitterPos; }; #pragma pack(pop) #pragma pack(pop, PragmaWindowPosition) void SaveWindowSize(const RECT &rect, bool maximized) { CSysString keyName = kCUBasePath; CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); key.Create(HKEY_CURRENT_USER, keyName); CWindowPosition position; position.Rect = rect; position.Maximized = maximized ? 1: 0; key.SetValue(kPositionValueName, &position, sizeof(position)); } bool ReadWindowSize(RECT &rect, bool &maximized) { CSysString keyName = kCUBasePath; CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); if(key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS) return false; CByteBuffer buffer; UINT32 size; if (key.QueryValue(kPositionValueName, buffer, size) != ERROR_SUCCESS) return false; if (size != sizeof(CWindowPosition)) return false; const CWindowPosition &position = *(const CWindowPosition *)(const BYTE *)buffer; rect = position.Rect; maximized = (position.Maximized != 0); return true; } void SavePanelsInfo(UINT32 numPanels, UINT32 currentPanel, UINT32 splitterPos) { CSysString keyName = kCUBasePath; CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); key.Create(HKEY_CURRENT_USER, keyName); CPanelsInfo block; block.NumPanels = numPanels; block.CurrentPanel = currentPanel; block.SplitterPos = splitterPos; key.SetValue(kPanelsInfoValueName, &block, sizeof(block)); } bool ReadPanelsInfo(UINT32 &numPanels, UINT32 ¤tPanel, UINT32 &splitterPos) { CSysString keyName = kCUBasePath; CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); if(key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS) return false; CByteBuffer buffer; UINT32 size; if (key.QueryValue(kPanelsInfoValueName, buffer, size) != ERROR_SUCCESS) return false; if (size != sizeof(CPanelsInfo)) return false; const CPanelsInfo &block = *(const CPanelsInfo *)(const BYTE *)buffer; numPanels = block.NumPanels; currentPanel = block.CurrentPanel; splitterPos = block.SplitterPos; return true; } void SaveToolbarsMask(UINT32 toolbarMask) { CKey key; key.Create(HKEY_CURRENT_USER, kCUBasePath); key.SetValue(kToolbars, toolbarMask); } static const kDefaultToolbarMask = 8 | 4 | 1; UINT32 ReadToolbarsMask() { CKey key; if(key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) return kDefaultToolbarMask; UINT32 mask; if (key.QueryValue(kToolbars, mask) != ERROR_SUCCESS) return kDefaultToolbarMask; return mask; } static CSysString GetPanelPathName(UINT32 panelIndex) { TCHAR panelString[32]; ConvertUINT64ToString(panelIndex, panelString); return CSysString(kPanelPathValueName) + panelString; } void SavePanelPath(UINT32 panel, const CSysString &path) { CSysString keyName = kCUBasePath; CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); key.Create(HKEY_CURRENT_USER, keyName); key.SetValue(GetPanelPathName(panel), path); } bool ReadPanelPath(UINT32 panel, CSysString &path) { CSysString keyName = kCUBasePath; CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); if(key.Open(HKEY_CURRENT_USER, keyName, KEY_READ) != ERROR_SUCCESS) return false; return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS); } void SaveStringList(LPCTSTR valueName, const UStringVector &folders) { UINT32 sizeInChars = 0; int i; for (i = 0; i < folders.Size(); i++) sizeInChars += folders[i].Length() + 1; CBuffer buffer; buffer.SetCapacity(sizeInChars); int aPos = 0; for (i = 0; i < folders.Size(); i++) { wcscpy(buffer + aPos, folders[i]); aPos += folders[i].Length() + 1; } CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); key.Create(HKEY_CURRENT_USER, kCUBasePath); key.SetValue(valueName, buffer, sizeInChars * sizeof(wchar_t)); } void ReadStringList(LPCTSTR valueName, UStringVector &folders) { folders.Clear(); CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); if(key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) return; CByteBuffer buffer; UINT32 dataSize; if (key.QueryValue(valueName, buffer, dataSize) != ERROR_SUCCESS) return; if (dataSize % sizeof(wchar_t) != 0) return; const wchar_t *data = (const wchar_t *)(const BYTE *)buffer; int sizeInChars = dataSize / sizeof(wchar_t); UString string; for (int i = 0; i < sizeInChars; i++) { wchar_t c = data[i]; if (c == L'\0') { folders.Add(string); string.Empty(); } else string += c; } } void SaveFolderHistory(const UStringVector &folders) { SaveStringList(kFolderHistoryValueName, folders); } void ReadFolderHistory(UStringVector &folders) { ReadStringList(kFolderHistoryValueName, folders); } void SaveFastFolders(const UStringVector &folders) { SaveStringList(kFastFoldersValueName, folders); } void ReadFastFolders(UStringVector &folders) { ReadStringList(kFastFoldersValueName, folders); } void SaveCopyHistory(const UStringVector &folders) { SaveStringList(kCopyHistoryValueName, folders); } void ReadCopyHistory(UStringVector &folders) { ReadStringList(kCopyHistoryValueName, folders); } void AddUniqueStringToHeadOfList(UStringVector &list, const UString &string) { for(int i = 0; i < list.Size();) if (string.CollateNoCase(list[i]) == 0) list.Delete(i); else i++; list.Insert(0, string); }