mirror of
https://github.com/holub/mame
synced 2025-06-23 21:06:38 +03:00
279 lines
6.7 KiB
C++
279 lines
6.7 KiB
C++
// SysIconUtils.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#ifndef _UNICODE
|
|
#include "../../../Common/StringConvert.h"
|
|
#endif
|
|
|
|
#include "../../../Windows/FileDir.h"
|
|
|
|
#include "SysIconUtils.h"
|
|
|
|
#if defined(__MINGW32__) || defined(__MINGW64__)
|
|
#include <shlobj.h>
|
|
#else
|
|
#include <ShlObj.h>
|
|
#endif
|
|
|
|
#ifndef _UNICODE
|
|
extern bool g_IsNT;
|
|
#endif
|
|
|
|
int GetIconIndexForCSIDL(int csidl)
|
|
{
|
|
LPITEMIDLIST pidl = NULL;
|
|
SHGetSpecialFolderLocation(NULL, csidl, &pidl);
|
|
if (pidl)
|
|
{
|
|
SHFILEINFO shellInfo;
|
|
shellInfo.iIcon = 0;
|
|
const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL,
|
|
&shellInfo, sizeof(shellInfo),
|
|
SHGFI_PIDL | SHGFI_SYSICONINDEX);
|
|
/*
|
|
IMalloc *pMalloc;
|
|
SHGetMalloc(&pMalloc);
|
|
if (pMalloc)
|
|
{
|
|
pMalloc->Free(pidl);
|
|
pMalloc->Release();
|
|
}
|
|
*/
|
|
// we use OLE2.dll function here
|
|
CoTaskMemFree(pidl);
|
|
if (res)
|
|
return shellInfo.iIcon;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifndef _UNICODE
|
|
typedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
|
|
|
|
static struct C_SHGetFileInfo_Init
|
|
{
|
|
Func_SHGetFileInfoW f_SHGetFileInfoW;
|
|
C_SHGetFileInfo_Init()
|
|
{
|
|
f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(
|
|
Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"),
|
|
"SHGetFileInfoW");
|
|
}
|
|
} g_SHGetFileInfo_Init;
|
|
#endif
|
|
|
|
static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
|
|
{
|
|
#ifdef _UNICODE
|
|
return SHGetFileInfo
|
|
#else
|
|
if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW)
|
|
return 0;
|
|
return g_SHGetFileInfo_Init.f_SHGetFileInfoW
|
|
#endif
|
|
(pszPath, attrib, psfi, cbFileInfo, uFlags);
|
|
}
|
|
|
|
DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex)
|
|
{
|
|
#ifndef _UNICODE
|
|
if (!g_IsNT)
|
|
{
|
|
SHFILEINFO shellInfo;
|
|
const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
|
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
|
|
iconIndex = shellInfo.iIcon;
|
|
return res;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SHFILEINFOW shellInfo;
|
|
const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
|
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
|
|
iconIndex = shellInfo.iIcon;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
/*
|
|
DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
|
|
{
|
|
#ifndef _UNICODE
|
|
if (!g_IsNT)
|
|
{
|
|
SHFILEINFO shellInfo;
|
|
shellInfo.szTypeName[0] = 0;
|
|
DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
|
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
|
|
if (typeName)
|
|
*typeName = GetUnicodeString(shellInfo.szTypeName);
|
|
iconIndex = shellInfo.iIcon;
|
|
return res;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SHFILEINFOW shellInfo;
|
|
shellInfo.szTypeName[0] = 0;
|
|
DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
|
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
|
|
if (typeName)
|
|
*typeName = shellInfo.szTypeName;
|
|
iconIndex = shellInfo.iIcon;
|
|
return res;
|
|
}
|
|
}
|
|
*/
|
|
|
|
static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, unsigned &insertPos)
|
|
{
|
|
unsigned left = 0, right = vect.Size();
|
|
while (left != right)
|
|
{
|
|
const unsigned mid = (left + right) / 2;
|
|
const DWORD midAttrib = vect[mid].Attrib;
|
|
if (attrib == midAttrib)
|
|
return (int)mid;
|
|
if (attrib < midAttrib)
|
|
right = mid;
|
|
else
|
|
left = mid + 1;
|
|
}
|
|
insertPos = left;
|
|
return -1;
|
|
}
|
|
|
|
static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, unsigned &insertPos)
|
|
{
|
|
unsigned left = 0, right = vect.Size();
|
|
while (left != right)
|
|
{
|
|
const unsigned mid = (left + right) / 2;
|
|
const int compare = MyStringCompareNoCase(ext, vect[mid].Ext);
|
|
if (compare == 0)
|
|
return (int)mid;
|
|
if (compare < 0)
|
|
right = mid;
|
|
else
|
|
left = mid + 1;
|
|
}
|
|
insertPos = left;
|
|
return -1;
|
|
}
|
|
|
|
int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
|
|
{
|
|
int dotPos = -1;
|
|
unsigned i;
|
|
for (i = 0;; i++)
|
|
{
|
|
const wchar_t c = fileName[i];
|
|
if (c == 0)
|
|
break;
|
|
if (c == '.')
|
|
dotPos = (int)i;
|
|
}
|
|
|
|
/*
|
|
if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0)
|
|
{
|
|
char s[256];
|
|
sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib);
|
|
OutputDebugStringA(s);
|
|
OutputDebugStringW(fileName);
|
|
}
|
|
*/
|
|
|
|
if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)
|
|
{
|
|
unsigned insertPos = 0;
|
|
const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
|
|
if (index >= 0)
|
|
{
|
|
// if (typeName) *typeName = _attribMap[index].TypeName;
|
|
return _attribMap[(unsigned)index].IconIndex;
|
|
}
|
|
CAttribIconPair pair;
|
|
GetRealIconIndex(
|
|
#ifdef UNDER_CE
|
|
FTEXT("\\")
|
|
#endif
|
|
FTEXT("__DIR__")
|
|
, attrib, pair.IconIndex
|
|
// , pair.TypeName
|
|
);
|
|
|
|
/*
|
|
char s[256];
|
|
sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
|
|
OutputDebugStringA(s);
|
|
*/
|
|
|
|
pair.Attrib = attrib;
|
|
_attribMap.Insert(insertPos, pair);
|
|
// if (typeName) *typeName = pair.TypeName;
|
|
return pair.IconIndex;
|
|
}
|
|
|
|
const wchar_t *ext = fileName + dotPos + 1;
|
|
unsigned insertPos = 0;
|
|
const int index = FindInSorted_Ext(_extMap, ext, insertPos);
|
|
if (index >= 0)
|
|
{
|
|
const CExtIconPair &pa = _extMap[index];
|
|
// if (typeName) *typeName = pa.TypeName;
|
|
return pa.IconIndex;
|
|
}
|
|
|
|
for (i = 0;; i++)
|
|
{
|
|
const wchar_t c = ext[i];
|
|
if (c == 0)
|
|
break;
|
|
if (c < L'0' || c > L'9')
|
|
break;
|
|
}
|
|
if (i != 0 && ext[i] == 0)
|
|
{
|
|
// GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003
|
|
if (!SplitIconIndex_Defined)
|
|
{
|
|
GetRealIconIndex(
|
|
#ifdef UNDER_CE
|
|
FTEXT("\\")
|
|
#endif
|
|
FTEXT("__FILE__.001"), 0, SplitIconIndex);
|
|
SplitIconIndex_Defined = true;
|
|
}
|
|
return SplitIconIndex;
|
|
}
|
|
|
|
CExtIconPair pair;
|
|
pair.Ext = ext;
|
|
GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex);
|
|
_extMap.Insert(insertPos, pair);
|
|
// if (typeName) *typeName = pair.TypeName;
|
|
return pair.IconIndex;
|
|
}
|
|
|
|
/*
|
|
int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)
|
|
{
|
|
return GetIconIndex(attrib, fileName, NULL);
|
|
}
|
|
*/
|
|
|
|
HIMAGELIST GetSysImageList(bool smallIcons)
|
|
{
|
|
SHFILEINFO shellInfo;
|
|
return (HIMAGELIST)SHGetFileInfo(TEXT(""),
|
|
FILE_ATTRIBUTE_NORMAL |
|
|
FILE_ATTRIBUTE_DIRECTORY,
|
|
&shellInfo, sizeof(shellInfo),
|
|
SHGFI_USEFILEATTRIBUTES |
|
|
SHGFI_SYSICONINDEX |
|
|
(smallIcons ? SHGFI_SMALLICON : SHGFI_ICON));
|
|
}
|