mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[FONTEXT] Cache attributes, handle sorting
This commit is contained in:
parent
cb9b538725
commit
91e63ee0b5
11 changed files with 271 additions and 100 deletions
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: CFontMenu implementation
|
* PURPOSE: CFontMenu implementation
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -58,7 +58,7 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl, PCUITEM
|
||||||
const FontPidlEntry* fontEntry = _FontFromIL(apidl[n]);
|
const FontPidlEntry* fontEntry = _FontFromIL(apidl[n]);
|
||||||
if (fontEntry)
|
if (fontEntry)
|
||||||
{
|
{
|
||||||
CStringW File = g_FontCache->Filename(fontEntry, true);
|
CStringW File = g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
|
||||||
if (!File.IsEmpty())
|
if (!File.IsEmpty())
|
||||||
{
|
{
|
||||||
// Now append the path (+ nullterminator) to the buffer
|
// Now append the path (+ nullterminator) to the buffer
|
||||||
|
@ -94,36 +94,8 @@ HRESULT _CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder, UINT cidl, PCUITEM
|
||||||
pDrop->pt.x = pDrop->pt.y = 0;
|
pDrop->pt.x = pDrop->pt.y = 0;
|
||||||
pDrop-> fNC = NULL;
|
pDrop-> fNC = NULL;
|
||||||
|
|
||||||
// Prepare the format descriptors
|
hr = DataObject_SetData(*(IDataObject**)ppvOut, CF_HDROP, data, offset);
|
||||||
STGMEDIUM medium = {0};
|
FAILED_UNEXPECTEDLY(hr);
|
||||||
medium.tymed = TYMED_HGLOBAL;
|
|
||||||
|
|
||||||
// Copy the data to an HGLOBAL
|
|
||||||
medium.hGlobal = GlobalAlloc(GHND, offset);
|
|
||||||
if (medium.hGlobal)
|
|
||||||
{
|
|
||||||
LPVOID blob = GlobalLock(medium.hGlobal);
|
|
||||||
if (blob)
|
|
||||||
{
|
|
||||||
CopyMemory(blob, (BYTE*)data, offset);
|
|
||||||
GlobalUnlock(medium.hGlobal);
|
|
||||||
|
|
||||||
CComPtr<IDataObject> spDataObject(*(IDataObject**)ppvOut);
|
|
||||||
if (spDataObject)
|
|
||||||
{
|
|
||||||
FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
|
||||||
hr = spDataObject->SetData(&etc, &medium, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR("Unable to lock the hGlobal?!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR("Unable to allocate %u bytes for the hGlobal\n", offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: CEnumFonts implementation
|
* PURPOSE: CEnumFonts implementation
|
||||||
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: font list cache handling
|
* PURPOSE: font list cache handling
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -14,7 +14,11 @@ CFontCache* g_FontCache = NULL;
|
||||||
CFontInfo::CFontInfo(LPCWSTR name)
|
CFontInfo::CFontInfo(LPCWSTR name)
|
||||||
: m_Name(name)
|
: m_Name(name)
|
||||||
, m_FileRead(false)
|
, m_FileRead(false)
|
||||||
|
, m_AttrsRead(false)
|
||||||
|
, m_FileWriteTime({})
|
||||||
|
, m_dwFileAttributes(0)
|
||||||
{
|
{
|
||||||
|
m_FileSize.QuadPart = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CStringW& CFontInfo::Name() const
|
const CStringW& CFontInfo::Name() const
|
||||||
|
@ -62,7 +66,52 @@ const CStringW& CFontInfo::File()
|
||||||
return m_File;
|
return m_File;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CFontInfo::ReadAttrs()
|
||||||
|
{
|
||||||
|
CStringW File = g_FontCache->Filename(this, true);
|
||||||
|
|
||||||
|
m_AttrsRead = true;
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW findFileData;
|
||||||
|
HANDLE hFile = FindFirstFileW(File, &findFileData);
|
||||||
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
|
||||||
|
// File write time
|
||||||
|
FileTimeToLocalFileTime(&findFileData.ftLastWriteTime, &m_FileWriteTime);
|
||||||
|
|
||||||
|
// File size
|
||||||
|
m_FileSize.HighPart = findFileData.nFileSizeHigh;
|
||||||
|
m_FileSize.LowPart = findFileData.nFileSizeLow;
|
||||||
|
|
||||||
|
m_dwFileAttributes = findFileData.dwFileAttributes;
|
||||||
|
FindClose(hFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const LARGE_INTEGER& CFontInfo::FileSize()
|
||||||
|
{
|
||||||
|
if (!m_AttrsRead)
|
||||||
|
ReadAttrs();
|
||||||
|
|
||||||
|
return m_FileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FILETIME& CFontInfo::FileWriteTime()
|
||||||
|
{
|
||||||
|
if (!m_AttrsRead)
|
||||||
|
ReadAttrs();
|
||||||
|
|
||||||
|
return m_FileWriteTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD CFontInfo::FileAttributes()
|
||||||
|
{
|
||||||
|
if (!m_AttrsRead)
|
||||||
|
ReadAttrs();
|
||||||
|
|
||||||
|
return m_dwFileAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
CFontCache::CFontCache()
|
CFontCache::CFontCache()
|
||||||
{
|
{
|
||||||
|
@ -93,23 +142,31 @@ CStringW CFontCache::Name(size_t Index)
|
||||||
return m_Fonts[Index].Name();
|
return m_Fonts[Index].Name();
|
||||||
}
|
}
|
||||||
|
|
||||||
CStringW CFontCache::Filename(const FontPidlEntry* fontEntry, bool alwaysFullPath)
|
CFontInfo* CFontCache::Find(const FontPidlEntry* fontEntry)
|
||||||
{
|
{
|
||||||
CStringW File;
|
|
||||||
|
|
||||||
if (fontEntry->Index < m_Fonts.GetCount())
|
if (fontEntry->Index < m_Fonts.GetCount())
|
||||||
{
|
{
|
||||||
CFontInfo& info = m_Fonts[fontEntry->Index];
|
if (m_Fonts[fontEntry->Index].Name().CompareNoCase(fontEntry->Name) == 0)
|
||||||
|
return &m_Fonts[fontEntry->Index];
|
||||||
if (info.Name().CompareNoCase(fontEntry->Name) == 0)
|
|
||||||
File = info.File();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (UINT n = 0; File.IsEmpty() && n < Size(); ++n)
|
for (UINT n = 0; n < Size(); ++n)
|
||||||
{
|
{
|
||||||
if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
|
if (m_Fonts[n].Name().CompareNoCase(fontEntry->Name) == 0)
|
||||||
File = m_Fonts[n].File();
|
{
|
||||||
|
return &m_Fonts[n];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CStringW CFontCache::Filename(CFontInfo* info, bool alwaysFullPath)
|
||||||
|
{
|
||||||
|
CStringW File;
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
File = info->File();
|
||||||
|
|
||||||
if (!File.IsEmpty() && alwaysFullPath)
|
if (!File.IsEmpty() && alwaysFullPath)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +176,7 @@ CStringW CFontCache::Filename(const FontPidlEntry* fontEntry, bool alwaysFullPat
|
||||||
File = m_FontFolderPath + File;
|
File = m_FontFolderPath + File;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return File;
|
return File;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: font list cache handling
|
* PURPOSE: font list cache handling
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -14,12 +14,24 @@ private:
|
||||||
CStringW m_Name;
|
CStringW m_Name;
|
||||||
CStringW m_File;
|
CStringW m_File;
|
||||||
bool m_FileRead;
|
bool m_FileRead;
|
||||||
|
|
||||||
|
bool m_AttrsRead;
|
||||||
|
LARGE_INTEGER m_FileSize;
|
||||||
|
FILETIME m_FileWriteTime;
|
||||||
|
DWORD m_dwFileAttributes;
|
||||||
|
|
||||||
|
void ReadAttrs();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CFontInfo(LPCWSTR name = L"");
|
CFontInfo(LPCWSTR name = L"");
|
||||||
|
|
||||||
const CStringW& Name() const;
|
const CStringW& Name() const; // Font display name stored in the registry
|
||||||
const CStringW& File();
|
|
||||||
const bool Valid() const;
|
const bool Valid() const;
|
||||||
|
|
||||||
|
const CStringW& File(); // Full path or file, depending on how it's stored in the registry
|
||||||
|
const LARGE_INTEGER& FileSize();
|
||||||
|
const FILETIME& FileWriteTime();
|
||||||
|
DWORD FileAttributes();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,8 +52,10 @@ public:
|
||||||
const CStringW& FontPath() const { return m_FontFolderPath; }
|
const CStringW& FontPath() const { return m_FontFolderPath; }
|
||||||
|
|
||||||
size_t Size();
|
size_t Size();
|
||||||
CStringW Name(size_t Index);
|
CStringW Name(size_t Index); // Font display name stored in the registry
|
||||||
CStringW Filename(const FontPidlEntry* fontEntry, bool alwaysFullPath = false);
|
|
||||||
|
CFontInfo* Find(const FontPidlEntry* fontEntry);
|
||||||
|
CStringW Filename(CFontInfo* info, bool alwaysFullPath = false);
|
||||||
|
|
||||||
friend class CFontExtModule;
|
friend class CFontExtModule;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: CFontExt implementation
|
* PURPOSE: CFontExt implementation
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019-2021 Mark Jansen <mark.jansen@reactos.org>
|
||||||
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(fontext);
|
WINE_DEFAULT_DEBUG_CHANNEL(fontext);
|
||||||
|
|
||||||
|
#ifndef SHCIDS_ALLFIELDS
|
||||||
|
#define SHCIDS_ALLFIELDS 0x80000000L
|
||||||
|
#endif
|
||||||
|
|
||||||
struct FolderViewColumns
|
struct FolderViewColumns
|
||||||
{
|
{
|
||||||
|
@ -20,6 +23,15 @@ struct FolderViewColumns
|
||||||
int fmt;
|
int fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum font_columns
|
||||||
|
{
|
||||||
|
FONTEXT_COL_NAME,
|
||||||
|
FONTEXT_COL_FILENAME,
|
||||||
|
FONTEXT_COL_SIZE,
|
||||||
|
FONTEXT_COL_MODIFIED,
|
||||||
|
FONTEXT_COL_ATTR,
|
||||||
|
};
|
||||||
|
|
||||||
static FolderViewColumns g_ColumnDefs[] =
|
static FolderViewColumns g_ColumnDefs[] =
|
||||||
{
|
{
|
||||||
{ IDS_COL_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 25, LVCFMT_LEFT },
|
{ IDS_COL_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 25, LVCFMT_LEFT },
|
||||||
|
@ -140,7 +152,7 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name, ReactOS specific?
|
// Name, ReactOS specific?
|
||||||
if (iColumn == 0)
|
if (iColumn == FONTEXT_COL_NAME)
|
||||||
return GetDisplayNameOf(pidl, 0, &psd->str);
|
return GetDisplayNameOf(pidl, 0, &psd->str);
|
||||||
|
|
||||||
const FontPidlEntry* fontEntry = _FontFromIL(pidl);
|
const FontPidlEntry* fontEntry = _FontFromIL(pidl);
|
||||||
|
@ -151,41 +163,28 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got here, we are in details view!
|
// If we got here, we are in details view!
|
||||||
// Let's see if we got info about this file that we can re-use
|
auto info = g_FontCache->Find(fontEntry);
|
||||||
if (m_LastDetailsFontName != fontEntry->Name)
|
if (info == nullptr)
|
||||||
{
|
{
|
||||||
CStringW File = g_FontCache->Filename(fontEntry, true);
|
ERR("Unable to query info about %S\n", fontEntry->Name);
|
||||||
HANDLE hFile = FindFirstFileW(File, &m_LastDetailsFileData);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
m_LastDetailsFontName.Empty();
|
|
||||||
ERR("Unable to query info about %S\n", File.GetString());
|
|
||||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
FindClose(hFile);
|
|
||||||
m_LastDetailsFontName = fontEntry->Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Most code borrowed from CFSFolder::GetDetailsOf
|
|
||||||
FILETIME lft;
|
|
||||||
SYSTEMTIME time;
|
|
||||||
int ret;
|
int ret;
|
||||||
LARGE_INTEGER FileSize;
|
|
||||||
CStringA AttrLetters;
|
CStringA AttrLetters;
|
||||||
|
DWORD dwAttributes;
|
||||||
|
SYSTEMTIME time;
|
||||||
switch (iColumn)
|
switch (iColumn)
|
||||||
{
|
{
|
||||||
case 1: // Filename
|
case FONTEXT_COL_FILENAME:
|
||||||
return SHSetStrRet(&psd->str, m_LastDetailsFileData.cFileName);
|
return SHSetStrRet(&psd->str, PathFindFileNameW(info->File()));
|
||||||
case 2: // Size
|
case FONTEXT_COL_SIZE:
|
||||||
psd->str.uType = STRRET_CSTR;
|
psd->str.uType = STRRET_CSTR;
|
||||||
FileSize.HighPart = m_LastDetailsFileData.nFileSizeHigh;
|
StrFormatKBSizeA(info->FileSize().QuadPart, psd->str.cStr, MAX_PATH);
|
||||||
FileSize.LowPart = m_LastDetailsFileData.nFileSizeLow;
|
|
||||||
StrFormatKBSizeA(FileSize.QuadPart, psd->str.cStr, MAX_PATH);
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
case 3: // Modified
|
case FONTEXT_COL_MODIFIED:
|
||||||
FileTimeToLocalFileTime(&m_LastDetailsFileData.ftLastWriteTime, &lft);
|
|
||||||
FileTimeToSystemTime (&lft, &time);
|
|
||||||
psd->str.uType = STRRET_CSTR;
|
psd->str.uType = STRRET_CSTR;
|
||||||
|
FileTimeToSystemTime(&info->FileWriteTime(), &time);
|
||||||
ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, psd->str.cStr, MAX_PATH);
|
ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, psd->str.cStr, MAX_PATH);
|
||||||
if (ret < 1)
|
if (ret < 1)
|
||||||
{
|
{
|
||||||
|
@ -195,7 +194,7 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
|
||||||
psd->str.cStr[ret-1] = ' ';
|
psd->str.cStr[ret-1] = ' ';
|
||||||
GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &psd->str.cStr[ret], MAX_PATH - ret);
|
GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &psd->str.cStr[ret], MAX_PATH - ret);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
case 4: // Attributes
|
case FONTEXT_COL_ATTR:
|
||||||
AttrLetters.LoadString(IDS_COL_ATTR_LETTERS);
|
AttrLetters.LoadString(IDS_COL_ATTR_LETTERS);
|
||||||
if (AttrLetters.GetLength() != 5)
|
if (AttrLetters.GetLength() != 5)
|
||||||
{
|
{
|
||||||
|
@ -203,16 +202,17 @@ STDMETHODIMP CFontExt::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDET
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
psd->str.uType = STRRET_CSTR;
|
psd->str.uType = STRRET_CSTR;
|
||||||
|
dwAttributes = info->FileAttributes();
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
if (dwAttributes & FILE_ATTRIBUTE_READONLY)
|
||||||
psd->str.cStr[ret++] = AttrLetters[0];
|
psd->str.cStr[ret++] = AttrLetters[0];
|
||||||
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||||
psd->str.cStr[ret++] = AttrLetters[1];
|
psd->str.cStr[ret++] = AttrLetters[1];
|
||||||
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
|
if (dwAttributes & FILE_ATTRIBUTE_SYSTEM)
|
||||||
psd->str.cStr[ret++] = AttrLetters[2];
|
psd->str.cStr[ret++] = AttrLetters[2];
|
||||||
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
|
if (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)
|
||||||
psd->str.cStr[ret++] = AttrLetters[3];
|
psd->str.cStr[ret++] = AttrLetters[3];
|
||||||
if (m_LastDetailsFileData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
if (dwAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
||||||
psd->str.cStr[ret++] = AttrLetters[4];
|
psd->str.cStr[ret++] = AttrLetters[4];
|
||||||
psd->str.cStr[ret] = '\0';
|
psd->str.cStr[ret] = '\0';
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -262,7 +262,53 @@ STDMETHODIMP CFontExt::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUID
|
||||||
if (!fontEntry1 || !fontEntry2)
|
if (!fontEntry1 || !fontEntry2)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
int result = (int)fontEntry1->Index - (int)fontEntry2->Index;
|
int result;
|
||||||
|
DWORD sortMode = lParam & 0xFFFF0000;
|
||||||
|
DWORD column = lParam & 0x0000FFFF;
|
||||||
|
if (sortMode == SHCIDS_ALLFIELDS)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
result = (int)fontEntry1->Index - (int)fontEntry2->Index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto info1 = g_FontCache->Find(fontEntry1);
|
||||||
|
auto info2 = g_FontCache->Find(fontEntry2);
|
||||||
|
|
||||||
|
if (!info1 || !info2)
|
||||||
|
{
|
||||||
|
ERR("Unable to find font %S or %S in cache!\n", fontEntry1->Name, fontEntry2->Name);
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case 0xffff:
|
||||||
|
/* ROS bug? */
|
||||||
|
case FONTEXT_COL_NAME:
|
||||||
|
// These items are already ordered by name
|
||||||
|
result = (int)fontEntry1->Index - (int)fontEntry2->Index;
|
||||||
|
break;
|
||||||
|
case FONTEXT_COL_FILENAME:
|
||||||
|
result = wcsicmp(PathFindFileNameW(info1->File()), PathFindFileNameW(info2->File()));
|
||||||
|
break;
|
||||||
|
case FONTEXT_COL_SIZE:
|
||||||
|
result = (int)info1->FileSize().HighPart - info2->FileSize().HighPart;
|
||||||
|
if (result == 0)
|
||||||
|
result = (int)info1->FileSize().LowPart - info2->FileSize().LowPart;
|
||||||
|
break;
|
||||||
|
case FONTEXT_COL_MODIFIED:
|
||||||
|
result = CompareFileTime(&info1->FileWriteTime(), &info2->FileWriteTime());
|
||||||
|
break;
|
||||||
|
case FONTEXT_COL_ATTR:
|
||||||
|
// FIXME: how to compare attributes?
|
||||||
|
result = (int)info1->FileAttributes() - info2->FileAttributes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR("Unimplemented column %u\n", column);
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MAKE_COMPARE_HRESULT(result);
|
return MAKE_COMPARE_HRESULT(result);
|
||||||
}
|
}
|
||||||
|
@ -341,7 +387,7 @@ STDMETHODIMP CFontExt::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_
|
||||||
if (fontEntry)
|
if (fontEntry)
|
||||||
{
|
{
|
||||||
DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL;
|
DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
CStringW File = g_FontCache->Filename(fontEntry);
|
CStringW File = g_FontCache->Filename(g_FontCache->Find(fontEntry));
|
||||||
// Just create a default icon extractor based on the filename
|
// Just create a default icon extractor based on the filename
|
||||||
// We might want to create a preview with the font to get really fancy one day.
|
// We might want to create a preview with the font to get really fancy one day.
|
||||||
return SHCreateFileExtractIconW(File, dwAttributes, riid, ppvOut);
|
return SHCreateFileExtractIconW(File, dwAttributes, riid, ppvOut);
|
||||||
|
@ -385,6 +431,15 @@ STDMETHODIMP CFontExt::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPS
|
||||||
if (!fontEntry)
|
if (!fontEntry)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
|
if (dwFlags == SHGDN_FORPARSING)
|
||||||
|
{
|
||||||
|
CStringW File = g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
|
||||||
|
if (!File.IsEmpty())
|
||||||
|
{
|
||||||
|
return SHSetStrRet(strRet, File);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SHSetStrRet(strRet, fontEntry->Name);
|
return SHSetStrRet(strRet, fontEntry->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: CFontExt definition
|
* PURPOSE: CFontExt definition
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
|
||||||
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
* Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@ class CFontExt :
|
||||||
public IDropTarget
|
public IDropTarget
|
||||||
{
|
{
|
||||||
CComHeapPtr<ITEMIDLIST> m_Folder;
|
CComHeapPtr<ITEMIDLIST> m_Folder;
|
||||||
CStringW m_LastDetailsFontName;
|
|
||||||
WIN32_FIND_DATAW m_LastDetailsFileData;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: CFontMenu implementation
|
* PURPOSE: CFontMenu implementation
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -69,7 +69,7 @@ static void RunFontViewer(HWND hwnd, const FontPidlEntry* fontEntry)
|
||||||
WCHAR FontViewerPath[MAX_PATH] = L"%SystemRoot%\\System32\\fontview.exe";
|
WCHAR FontViewerPath[MAX_PATH] = L"%SystemRoot%\\System32\\fontview.exe";
|
||||||
WCHAR FontPathArg[MAX_PATH + 3];
|
WCHAR FontPathArg[MAX_PATH + 3];
|
||||||
|
|
||||||
CStringW Path = g_FontCache->Filename(fontEntry, true);
|
CStringW Path = g_FontCache->Filename(g_FontCache->Find(fontEntry), true);
|
||||||
if (!Path.IsEmpty())
|
if (!Path.IsEmpty())
|
||||||
{
|
{
|
||||||
// '/d' disables the install button
|
// '/d' disables the install button
|
||||||
|
@ -108,7 +108,7 @@ static HRESULT CALLBACK FontFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDa
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
case DFM_INVOKECOMMAND:
|
case DFM_INVOKECOMMAND:
|
||||||
// Preview is the only item we can handle
|
// Preview is the only item we handle
|
||||||
if (wParam == 0)
|
if (wParam == 0)
|
||||||
{
|
{
|
||||||
CComHeapPtr<CIDA> cida;
|
CComHeapPtr<CIDA> cida;
|
||||||
|
@ -123,6 +123,15 @@ static HRESULT CALLBACK FontFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDa
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
else if (wParam == DFM_CMD_PROPERTIES)
|
||||||
|
{
|
||||||
|
ERR("Default properties handling!\n");
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Unhandled DFM_INVOKECOMMAND(wParam=0x%x)\n", wParam);
|
||||||
|
}
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
case DFM_INVOKECOMMANDEX:
|
case DFM_INVOKECOMMANDEX:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: Shell extension entry point
|
* PURPOSE: Shell extension entry point
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: pidl handling
|
* PURPOSE: pidl handling
|
||||||
* COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Font Shell Extension
|
* PROJECT: ReactOS Font Shell Extension
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: pidl handling
|
* PURPOSE: pidl handling
|
||||||
* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
|
* COPYRIGHT: Copyright 2019 Mark Jansen <mark.jansen@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -12,7 +12,7 @@ struct FontPidlEntry
|
||||||
{
|
{
|
||||||
WORD cb;
|
WORD cb;
|
||||||
WORD Magic;
|
WORD Magic;
|
||||||
ULONG Index; // Informative only
|
ULONG Index; // Informative only, used for sorting
|
||||||
|
|
||||||
WCHAR Name[1];
|
WCHAR Name[1];
|
||||||
};
|
};
|
||||||
|
|
|
@ -546,4 +546,69 @@ static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const* pida, SIZE_T i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
inline
|
||||||
|
HRESULT DataObject_GetData(IDataObject* pDataObject, CLIPFORMAT clipformat, PVOID pBuffer, SIZE_T dwBufferSize)
|
||||||
|
{
|
||||||
|
FORMATETC fmt = { clipformat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
STGMEDIUM medium = { TYMED_NULL };
|
||||||
|
|
||||||
|
HRESULT hr = pDataObject->GetData(&fmt, &medium);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
LPVOID blob = GlobalLock(medium.hGlobal);
|
||||||
|
if (blob)
|
||||||
|
{
|
||||||
|
SIZE_T size = GlobalSize(medium.hGlobal);
|
||||||
|
if (size <= dwBufferSize)
|
||||||
|
{
|
||||||
|
CopyMemory(pBuffer, blob, size);
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
GlobalUnlock(medium.hGlobal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = STG_E_INVALIDHANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseStgMedium(&medium);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
HRESULT DataObject_SetData(IDataObject* pDataObject, CLIPFORMAT clipformat, PVOID pBuffer, SIZE_T dwBufferSize)
|
||||||
|
{
|
||||||
|
STGMEDIUM medium = { TYMED_HGLOBAL };
|
||||||
|
|
||||||
|
medium.hGlobal = GlobalAlloc(GHND, dwBufferSize);
|
||||||
|
if (!medium.hGlobal)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
HRESULT hr = E_UNEXPECTED;
|
||||||
|
LPVOID blob = GlobalLock(medium.hGlobal);
|
||||||
|
if (blob)
|
||||||
|
{
|
||||||
|
CopyMemory(blob, pBuffer, dwBufferSize);
|
||||||
|
GlobalUnlock(medium.hGlobal);
|
||||||
|
|
||||||
|
FORMATETC etc = { clipformat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
hr = pDataObject->SetData(&etc, &medium, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
GlobalFree(medium.hGlobal);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* __ROS_SHELL_UTILS_H */
|
#endif /* __ROS_SHELL_UTILS_H */
|
||||||
|
|
Loading…
Reference in a new issue