mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
243 lines
5.8 KiB
C++
243 lines
5.8 KiB
C++
/*
|
|
Copyright (C) 2013 Rainmeter Team
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "../Common/PathUtil.h"
|
|
#include "SkinRegistry.h"
|
|
#include "resource.h"
|
|
|
|
/*
|
|
** Returns the skin folder path relative to the skin folder (e.g. illustro\Clock).
|
|
*/
|
|
std::wstring SkinRegistry::GetFolderPath(int folderIndex) const
|
|
{
|
|
// Traverse |m_Folders| backwards until level 1 is reached.
|
|
const auto& skinFolder = m_Folders[folderIndex];
|
|
std::wstring path = skinFolder.name;
|
|
for (int i = skinFolder.level - 1, index = folderIndex; i >= 1; --i)
|
|
{
|
|
while (m_Folders[index].level != i)
|
|
{
|
|
--index;
|
|
}
|
|
|
|
path.insert(0, L"\\");
|
|
path.insert(0, m_Folders[index].name);
|
|
}
|
|
return path;
|
|
}
|
|
|
|
/*
|
|
** Finds the skin index for the specified skin folder path.
|
|
*/
|
|
int SkinRegistry::FindFolderIndex(const std::wstring& folderPath) const
|
|
{
|
|
if (folderPath.empty()) return -1;
|
|
|
|
const WCHAR* path = folderPath.c_str();
|
|
int len = 0;
|
|
while (path[len] && path[len] != L'\\') ++len;
|
|
|
|
int level = 1;
|
|
for (int i = 0, isize = (int)m_Folders.size(); i < isize; ++i)
|
|
{
|
|
const auto& skinFolder = m_Folders[i];
|
|
if (skinFolder.level == level)
|
|
{
|
|
if (skinFolder.name.length() == len && _wcsnicmp(skinFolder.name.c_str(), path, len) == 0)
|
|
{
|
|
path += len;
|
|
if (*path)
|
|
{
|
|
++path; // Skip backslash
|
|
len = 0;
|
|
while (path[len] && path[len] != L'\\') ++len;
|
|
}
|
|
else
|
|
{
|
|
// Match found
|
|
return i;
|
|
}
|
|
|
|
++level;
|
|
}
|
|
}
|
|
else if (skinFolder.level < level)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
SkinRegistry::Folder* SkinRegistry::FindFolder(const std::wstring& folderPath)
|
|
{
|
|
const int folderIndex = FindFolderIndex(folderPath);
|
|
return (folderIndex != -1) ? &m_Folders[folderIndex] : nullptr;
|
|
}
|
|
|
|
SkinRegistry::Indexes SkinRegistry::FindIndexes(const std::wstring& folderPath, const std::wstring& file)
|
|
{
|
|
const int folderIndex = FindFolderIndex(folderPath);
|
|
if (folderIndex != -1)
|
|
{
|
|
const Folder& skinFolder = m_Folders[folderIndex];
|
|
const WCHAR* fileSz = file.c_str();
|
|
for (size_t i = 0, isize = skinFolder.files.size(); i < isize; ++i)
|
|
{
|
|
if (_wcsicmp(skinFolder.files[i].c_str(), fileSz) == 0)
|
|
{
|
|
return Indexes(folderIndex, (int)i);
|
|
}
|
|
}
|
|
}
|
|
|
|
return Indexes::Invalid(); // Not found.
|
|
}
|
|
|
|
SkinRegistry::Indexes SkinRegistry::FindIndexesForID(UINT id)
|
|
{
|
|
if (id >= ID_CONFIG_FIRST && id <= ID_CONFIG_LAST)
|
|
{
|
|
// Check which skin was selected
|
|
for (size_t i = 0, isize = m_Folders.size(); i < isize; ++i)
|
|
{
|
|
const Folder& skinFolder = m_Folders[i];
|
|
if (id >= skinFolder.baseID &&
|
|
id < (skinFolder.baseID + skinFolder.files.size()))
|
|
{
|
|
return Indexes((int)i, (int)(id - skinFolder.baseID));
|
|
}
|
|
}
|
|
}
|
|
|
|
return Indexes::Invalid(); // Not found.
|
|
}
|
|
|
|
/*
|
|
** Re-scans all the subfolders of |path| for .ini files and populates |m_Folders|.
|
|
*/
|
|
void SkinRegistry::Populate(const std::wstring& path)
|
|
{
|
|
m_Folders.clear();
|
|
PopulateRecursive(path, L"", 0, 0);
|
|
}
|
|
|
|
int SkinRegistry::PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level)
|
|
{
|
|
WIN32_FIND_DATA fileData; // Data structure describes the file found
|
|
HANDLE hSearch; // Search handle returned by FindFirstFile
|
|
std::list<std::wstring> subfolders;
|
|
|
|
// Find all .ini files and subfolders
|
|
std::wstring filter = path + base;
|
|
filter += L"\\*";
|
|
|
|
hSearch = FindFirstFileEx(
|
|
filter.c_str(),
|
|
(IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard,
|
|
&fileData,
|
|
FindExSearchNameMatch,
|
|
nullptr,
|
|
0);
|
|
|
|
bool foundFiles = false;
|
|
if (hSearch != INVALID_HANDLE_VALUE)
|
|
{
|
|
Folder folder;
|
|
folder.baseID = ID_CONFIG_FIRST + index;
|
|
folder.active = 0;
|
|
folder.level = level;
|
|
|
|
do
|
|
{
|
|
const std::wstring filename = fileData.cFileName;
|
|
|
|
if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (!PathUtil::IsDotOrDotDot(fileData.cFileName) &&
|
|
!(level == 0 && wcscmp(L"@Backup", fileData.cFileName) == 0) &&
|
|
!(level == 0 && wcscmp(L"Backup", fileData.cFileName) == 0) &&
|
|
!(level == 1 && wcscmp(L"@Resources", fileData.cFileName) == 0))
|
|
{
|
|
subfolders.push_back(filename);
|
|
}
|
|
}
|
|
else if (level != 0)
|
|
{
|
|
// Check whether the extension is ".ini"
|
|
size_t filenameLen = filename.size();
|
|
if (filenameLen >= 4 && _wcsicmp(fileData.cFileName + (filenameLen - 4), L".ini") == 0)
|
|
{
|
|
foundFiles = true;
|
|
folder.files.push_back(filename);
|
|
++index;
|
|
}
|
|
}
|
|
}
|
|
while (FindNextFile(hSearch, &fileData));
|
|
|
|
FindClose(hSearch);
|
|
|
|
if (level > 0 && (foundFiles || !subfolders.empty()))
|
|
{
|
|
if (level == 1)
|
|
{
|
|
folder.name = base;
|
|
}
|
|
else
|
|
{
|
|
std::wstring::size_type pos = base.rfind(L'\\') + 1;
|
|
folder.name.assign(base, pos, base.length() - pos);
|
|
}
|
|
|
|
m_Folders.push_back(std::move(folder));
|
|
}
|
|
}
|
|
|
|
if (level != 0)
|
|
{
|
|
base += L'\\';
|
|
}
|
|
|
|
if (!subfolders.empty())
|
|
{
|
|
bool popFolder = !foundFiles;
|
|
|
|
std::list<std::wstring>::const_iterator iter = subfolders.begin();
|
|
for ( ; iter != subfolders.end(); ++iter)
|
|
{
|
|
int newIndex = PopulateRecursive(path, base + (*iter), index, level + 1);
|
|
if (newIndex != index)
|
|
{
|
|
popFolder = false;
|
|
}
|
|
|
|
index = newIndex;
|
|
}
|
|
|
|
if (popFolder)
|
|
{
|
|
m_Folders.pop_back();
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|