// ViewSettings.h #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/StringConvert.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 WCHAR *kPanelPathValueName = L"PanelPath"; static const TCHAR *kListMode = TEXT("ListMode"); static const TCHAR *kFolderHistoryValueName = TEXT("FolderHistory"); static const TCHAR *kFastFoldersValueName = TEXT("FolderShortcuts"); static const TCHAR *kCopyHistoryValueName = TEXT("CopyHistory"); /* class CColumnInfoSpec { UInt32 PropID; Byte IsVisible; UInt32 Width; }; struct CColumnHeader { UInt32 Version; UInt32 SortID; Byte Ascending; }; */ static const UInt32 kColumnInfoSpecHeader = 12; static const UInt32 kColumnHeaderSize = 12; static const UInt32 kColumnInfoVersion = 1; static NSynchronization::CCriticalSection g_RegistryOperationsCriticalSection; class CTempOutBufferSpec { CByteBuffer Buffer; UInt32 Size; UInt32 Pos; public: operator const Byte *() const { return (const Byte *)Buffer; } void Init(UInt32 dataSize) { Buffer.SetCapacity(dataSize); Size = dataSize; Pos = 0; } void WriteByte(Byte value) { if (Pos >= Size) throw "overflow"; ((Byte *)Buffer)[Pos++] = value; } void WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void WriteBool(bool value) { WriteUInt32(value ? 1 : 0); } }; class CTempInBufferSpec { public: Byte *Buffer; UInt32 Size; UInt32 Pos; Byte ReadByte() { if (Pos >= Size) throw "overflow"; return Buffer[Pos++]; } UInt32 ReadUInt32() { UInt32 value = 0; for (int i = 0; i < 4; i++) value |= (((UInt32)ReadByte()) << (8 * i)); return value; } bool ReadBool() { return (ReadUInt32() != 0); } }; void SaveListViewInfo(const UString &id, const CListViewInfo &viewInfo) { const CObjectVector &columns = viewInfo.Columns; CTempOutBufferSpec buffer; UInt32 dataSize = kColumnHeaderSize + kColumnInfoSpecHeader * columns.Size(); buffer.Init(dataSize); buffer.WriteUInt32(kColumnInfoVersion); buffer.WriteUInt32(viewInfo.SortID); buffer.WriteBool(viewInfo.Ascending); for(int i = 0; i < columns.Size(); i++) { const CColumnInfo &column = columns[i]; buffer.WriteUInt32(column.PropID); buffer.WriteBool(column.IsVisible); buffer.WriteUInt32(column.Width); } { NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); CSysString keyName = kCUBasePath; keyName += kKeyNameDelimiter; keyName += kCulumnsKeyName; CKey key; key.Create(HKEY_CURRENT_USER, keyName); key.SetValue(GetSystemString(id), (const Byte *)buffer, dataSize); } } void ReadListViewInfo(const UString &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(GetSystemString(id), buffer, size) != ERROR_SUCCESS) return; } if (size < kColumnHeaderSize) return; CTempInBufferSpec inBuffer; inBuffer.Size = size; inBuffer.Buffer = (Byte *)buffer; inBuffer.Pos = 0; UInt32 version = inBuffer.ReadUInt32(); if (version != kColumnInfoVersion) return; viewInfo.SortID = inBuffer.ReadUInt32(); viewInfo.Ascending = inBuffer.ReadBool(); size -= kColumnHeaderSize; if (size % kColumnInfoSpecHeader != 0) return; int numItems = size / kColumnInfoSpecHeader; columns.Reserve(numItems); for(int i = 0; i < numItems; i++) { CColumnInfo columnInfo; columnInfo.PropID = inBuffer.ReadUInt32(); columnInfo.IsVisible = inBuffer.ReadBool(); columnInfo.Width = inBuffer.ReadUInt32(); columns.Add(columnInfo); } } static const UInt32 kWindowPositionHeaderSize = 5 * 4; static const UInt32 kPanelsInfoHeaderSize = 3 * 4; /* struct CWindowPosition { RECT Rect; UInt32 Maximized; }; struct CPanelsInfo { UInt32 NumPanels; UInt32 CurrentPanel; UInt32 SplitterPos; }; */ 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; CTempOutBufferSpec buffer; buffer.Init(kWindowPositionHeaderSize); buffer.WriteUInt32(rect.left); buffer.WriteUInt32(rect.top); buffer.WriteUInt32(rect.right); buffer.WriteUInt32(rect.bottom); buffer.WriteBool(maximized); key.SetValue(kPositionValueName, (const Byte *)buffer, kWindowPositionHeaderSize); } 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 != kWindowPositionHeaderSize) return false; CTempInBufferSpec inBuffer; inBuffer.Size = size; inBuffer.Buffer = (Byte *)buffer; inBuffer.Pos = 0; rect.left = inBuffer.ReadUInt32(); rect.top = inBuffer.ReadUInt32(); rect.right = inBuffer.ReadUInt32(); rect.bottom = inBuffer.ReadUInt32(); maximized = inBuffer.ReadBool(); 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); CTempOutBufferSpec buffer; buffer.Init(kPanelsInfoHeaderSize); buffer.WriteUInt32(numPanels); buffer.WriteUInt32(currentPanel); buffer.WriteUInt32(splitterPos); key.SetValue(kPanelsInfoValueName, (const Byte *)buffer, kPanelsInfoHeaderSize); } 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 != kPanelsInfoHeaderSize) return false; CTempInBufferSpec inBuffer; inBuffer.Size = size; inBuffer.Buffer = (Byte *)buffer; inBuffer.Pos = 0; numPanels = inBuffer.ReadUInt32(); currentPanel = inBuffer.ReadUInt32(); splitterPos = inBuffer.ReadUInt32(); return true; } void SaveToolbarsMask(UInt32 toolbarMask) { CKey key; key.Create(HKEY_CURRENT_USER, kCUBasePath); key.SetValue(kToolbars, toolbarMask); } static const UInt32 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 UString GetPanelPathName(UInt32 panelIndex) { WCHAR panelString[32]; ConvertUInt64ToString(panelIndex, panelString); return UString(kPanelPathValueName) + panelString; } void SavePanelPath(UInt32 panel, const UString &path) { CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); key.Create(HKEY_CURRENT_USER, kCUBasePath); key.SetValue(GetPanelPathName(panel), path); } bool ReadPanelPath(UInt32 panel, UString &path) { CKey key; NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection); if(key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) return false; return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS); } void SaveListMode(const CListMode &listMode) { CKey key; key.Create(HKEY_CURRENT_USER, kCUBasePath); UInt32 t = 0; for (int i = 0; i < 2; i++) t |= ((listMode.Panels[i]) & 0xFF) << (i * 8); key.SetValue(kListMode, t); } void ReadListMode(CListMode &listMode) { CKey key; listMode.Init(); if(key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) return; UInt32 t; if (key.QueryValue(kListMode, t) != ERROR_SUCCESS) return; for (int i = 0; i < 2; i++) { listMode.Panels[i] = (t & 0xFF); t >>= 8; } } 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 pos = 0; for (i = 0; i < folders.Size(); i++) { MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)folders[i]); pos += 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.CompareNoCase(list[i]) == 0) list.Delete(i); else i++; list.Insert(0, string); }