Index: src/ch/FeedbackNotEnoughSpaceDlg.cpp =================================================================== diff -u -N -r3c3018d15591811e0b3cb35f43ceb31f4914f47e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/FeedbackNotEnoughSpaceDlg.cpp (.../FeedbackNotEnoughSpaceDlg.cpp) (revision 3c3018d15591811e0b3cb35f43ceb31f4914f47e) +++ src/ch/FeedbackNotEnoughSpaceDlg.cpp (.../FeedbackNotEnoughSpaceDlg.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -21,8 +21,8 @@ #include "FileInfo.h" #include "FeedbackNotEnoughSpaceDlg.h" #include "StringHelpers.h" -#include "..\Common\FileSupport.h" #include "FeedbackHandler.h" +#include "FileSupport.h" #ifdef _DEBUG #define new DEBUG_NEW Index: src/ch/FileFilter.cpp =================================================================== diff -u -N -r6e8aa26e2428e3bc71099255c5911f57bc722100 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/FileFilter.cpp (.../FileFilter.cpp) (revision 6e8aa26e2428e3bc71099255c5911f57bc722100) +++ src/ch/FileFilter.cpp (.../FileFilter.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -231,7 +231,7 @@ m_bUseMask = false; m_astrMask.clear(); - GetConfigValue(rConfig, _T("IncludeMask.MaskList"), m_astrMask); + GetConfigValue(rConfig, _T("IncludeMask.MaskList.Mask"), m_astrMask); if(!GetConfigValue(rConfig, _T("ExcludeMask.Use"), m_bUseExcludeMask)) m_bUseExcludeMask = false; @@ -601,11 +601,13 @@ { m_vFilters.clear(); - std::vector vConfigs; + chcore::TConfigArray vConfigs; if(!rConfig.ExtractMultiSubConfigs(pszNodeName, vConfigs)) return false; - BOOST_FOREACH(const chcore::TConfig& rCfg, vConfigs) + + for(size_t stIndex = 0; stIndex < vConfigs.GetCount(); ++stIndex) { + const chcore::TConfig& rCfg = vConfigs.GetAt(stIndex); CFileFilter tFilter; tFilter.ReadFromConfig(rCfg); Index: src/ch/FileSupport.cpp =================================================================== diff -u -N --- src/ch/FileSupport.cpp (revision 0) +++ src/ch/FileSupport.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,101 @@ +/*************************************************************************** +* Copyright (C) 2001-2008 by J�zef Starosczyk * +* ixen@copyhandler.com * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU Library General Public License * +* (version 2) as published by the Free Software Foundation; * +* * +* 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 Library General Public * +* License along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#include "stdafx.h" +#include "wtypes.h" +#include "FileSupport.h" +//#include "tchar.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +__int64 SetFilePointer64(HANDLE hFile, __int64 llDistance, DWORD dwMoveMethod) +{ + LARGE_INTEGER li = { 0, 0 }; + LARGE_INTEGER liNew = { 0, 0 }; + + li.QuadPart = llDistance; + + if(!SetFilePointerEx(hFile, li, &liNew, dwMoveMethod)) + return -1; + + return liNew.QuadPart; +} + +__int64 GetFilePointer64(HANDLE hFile) +{ + return SetFilePointer64(hFile, 0, FILE_CURRENT); +} + +__int64 GetFileSize64(HANDLE hFile) +{ + LARGE_INTEGER li = { 0, 0 }; + + if(!GetFileSizeEx(hFile, &li)) + return -1; + + return li.QuadPart; +} + +bool SetFileSize64(LPCTSTR lpszFilename, __int64 llSize) +{ + HANDLE hFile = CreateFile(lpszFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(hFile == INVALID_HANDLE_VALUE) + return false; + + if(SetFilePointer64(hFile, llSize, FILE_BEGIN) == -1) + { + CloseHandle(hFile); + return false; + } + + if(!SetEndOfFile(hFile)) + { + CloseHandle(hFile); + return false; + } + + if(!CloseHandle(hFile)) + return false; + + return true; +} + +// disk support routines + +bool GetDynamicFreeSpace(LPCTSTR lpszPath, ull_t* pFree, ull_t* pTotal) +{ + ULARGE_INTEGER ui64Available, ui64Total; + if(!GetDiskFreeSpaceEx(lpszPath, &ui64Available, &ui64Total, NULL)) + { + if(pFree) + *pFree = 0; + if(pTotal) + *pTotal = 0; + return false; + } + else + { + if(pFree) + *pFree=ui64Available.QuadPart; + if(pTotal) + *pTotal=ui64Total.QuadPart; + return true; + } +} Index: src/common/FileSupport.cpp =================================================================== diff -u -N --- src/common/FileSupport.cpp (revision e02ef146420c494f7dfd5b216160dfcca23a3d7f) +++ src/common/FileSupport.cpp (revision 0) @@ -1,101 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2001-2008 by J�zef Starosczyk * -* ixen@copyhandler.com * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Library General Public License * -* (version 2) as published by the Free Software Foundation; * -* * -* 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 Library General Public * -* License along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include "stdafx.h" -#include "wtypes.h" -#include "FileSupport.h" -//#include "tchar.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - -__int64 SetFilePointer64(HANDLE hFile, __int64 llDistance, DWORD dwMoveMethod) -{ - LARGE_INTEGER li = { 0, 0 }; - LARGE_INTEGER liNew = { 0, 0 }; - - li.QuadPart = llDistance; - - if(!SetFilePointerEx(hFile, li, &liNew, dwMoveMethod)) - return -1; - - return liNew.QuadPart; -} - -__int64 GetFilePointer64(HANDLE hFile) -{ - return SetFilePointer64(hFile, 0, FILE_CURRENT); -} - -__int64 GetFileSize64(HANDLE hFile) -{ - LARGE_INTEGER li = { 0, 0 }; - - if(!GetFileSizeEx(hFile, &li)) - return -1; - - return li.QuadPart; -} - -bool SetFileSize64(LPCTSTR lpszFilename, __int64 llSize) -{ - HANDLE hFile = CreateFile(lpszFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if(hFile == INVALID_HANDLE_VALUE) - return false; - - if(SetFilePointer64(hFile, llSize, FILE_BEGIN) == -1) - { - CloseHandle(hFile); - return false; - } - - if(!SetEndOfFile(hFile)) - { - CloseHandle(hFile); - return false; - } - - if(!CloseHandle(hFile)) - return false; - - return true; -} - -// disk support routines - -bool GetDynamicFreeSpace(LPCTSTR lpszPath, ull_t* pFree, ull_t* pTotal) -{ - ULARGE_INTEGER ui64Available, ui64Total; - if(!GetDiskFreeSpaceEx(lpszPath, &ui64Available, &ui64Total, NULL)) - { - if(pFree) - *pFree = 0; - if(pTotal) - *pTotal = 0; - return false; - } - else - { - if(pFree) - *pFree=ui64Available.QuadPart; - if(pTotal) - *pTotal=ui64Total.QuadPart; - return true; - } -} Index: src/ch/FileSupport.h =================================================================== diff -u -N --- src/ch/FileSupport.h (revision 0) +++ src/ch/FileSupport.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,31 @@ +/*************************************************************************** +* Copyright (C) 2001-2008 by J�zef Starosczyk * +* ixen@copyhandler.com * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU Library General Public License * +* (version 2) as published by the Free Software Foundation; * +* * +* 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 Library General Public * +* License along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#ifndef __FILESUPPORT_ROUTINES_H__ +#define __FILESUPPORT_ROUTINES_H__ + +// file support routines +__int64 SetFilePointer64(HANDLE hFile, __int64 llDistance, DWORD dwMoveMethod); +__int64 GetFilePointer64(HANDLE hFile); +__int64 GetFileSize64(HANDLE hFile); +bool SetFileSize64(LPCTSTR lpszFilename, __int64 llSize); + +// disk support routines +bool GetDynamicFreeSpace(LPCTSTR lpszPath, ull_t* pFree, ull_t* pTotal); + +#endif \ No newline at end of file Index: src/common/FileSupport.h =================================================================== diff -u -N --- src/common/FileSupport.h (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/common/FileSupport.h (revision 0) @@ -1,31 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2001-2008 by J�zef Starosczyk * -* ixen@copyhandler.com * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Library General Public License * -* (version 2) as published by the Free Software Foundation; * -* * -* 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 Library General Public * -* License along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef __FILESUPPORT_ROUTINES_H__ -#define __FILESUPPORT_ROUTINES_H__ - -// file support routines -__int64 SetFilePointer64(HANDLE hFile, __int64 llDistance, DWORD dwMoveMethod); -__int64 GetFilePointer64(HANDLE hFile); -__int64 GetFileSize64(HANDLE hFile); -bool SetFileSize64(LPCTSTR lpszFilename, __int64 llSize); - -// disk support routines -bool GetDynamicFreeSpace(LPCTSTR lpszPath, ull_t* pFree, ull_t* pTotal); - -#endif \ No newline at end of file Index: src/ch/FolderDialog.cpp =================================================================== diff -u -N -r9ea1e103b5fa4ddfebf8028f121ce16e917eec04 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/FolderDialog.cpp (.../FolderDialog.cpp) (revision 9ea1e103b5fa4ddfebf8028f121ce16e917eec04) +++ src/ch/FolderDialog.cpp (.../FolderDialog.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -23,8 +23,8 @@ #include "memdc.h" #include "Theme Helpers.h" #include "shlobj.h" -#include "..\Common\FileSupport.h" #include "StringHelpers.h" +#include "FileSupport.h" #ifdef _DEBUG #define new DEBUG_NEW Index: src/ch/MainWnd.cpp =================================================================== diff -u -N -r3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f) +++ src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -35,6 +35,10 @@ #include #include #include "../libchcore/TWStringData.h" +#include "../common/TShellExtMenuConfig.h" +#include "../libchcore/TConfig.h" +#include "FileSupport.h" +#include "StringHelpers.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -53,8 +57,6 @@ #define TM_AUTOREMOVE 1000 #define TM_ACCEPTING 100 -extern CSharedConfigStruct* g_pscsShared; - extern int iCount; extern unsigned short msg[]; @@ -432,7 +434,7 @@ return FALSE; chcore::TWStringData wstrData(pszBuffer); - //AfxMessageBox(wstrData.GetData()); // TEMP = to remove before commit + AfxMessageBox(wstrData.GetData()); // TEMP = to remove before commit chcore::TTaskDefinition tTaskDefinition; tTaskDefinition.LoadFromString(wstrData); @@ -613,98 +615,167 @@ { chcore::TConfig& rConfig = GetConfig(); - // std config values - g_pscsShared->bShowFreeSpace=GetPropValue(rConfig); - + TShellExtMenuConfig cfgShellExt; + // experimental - doesn't work on all systems - g_pscsShared->bShowShortcutIcons=GetPropValue(rConfig); - g_pscsShared->uiFlags = (GetPropValue(rConfig) ? CSharedConfigStruct::eFlag_InterceptDragAndDrop : 0) | - (GetPropValue(rConfig) ? CSharedConfigStruct::eFlag_InterceptKeyboardActions : 0) | - (GetPropValue(rConfig) ? CSharedConfigStruct::eFlag_InterceptCtxMenuActions : 0); - - // sizes - for (int i=0;i<6;i++) - _tcscpy(g_pscsShared->szSizes[i], GetResManager().LoadString(IDS_BYTE_STRING+i)); + cfgShellExt.SetShowShortcutIcons(GetPropValue(rConfig)); - // convert to list of _COMMAND's - _COMMAND *pCommand = g_pscsShared->GetCommandsPtr(); + cfgShellExt.SetInterceptDragAndDrop(GetPropValue(rConfig)); + cfgShellExt.SetInterceptKeyboardActions(GetPropValue(rConfig)); + cfgShellExt.SetInterceptCtxMenuActions(GetPropValue(rConfig)); + TShellMenuItemPtr spRootItem = cfgShellExt.GetCommandRoot(); + // what kind of menu ? switch (wParam) { - case GC_DRAGDROP: + case eLocation_DragAndDropMenu: { - g_pscsShared->iCommandCount=3; - g_pscsShared->iShortcutsCount=0; - g_pscsShared->uiFlags |= (GetPropValue(rConfig) ? CSharedConfigStruct::DD_COPY_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::DD_MOVE_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG : 0); + bool bAddedAnyOption = false; + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPY_STRING), GetResManager().LoadString(IDS_MENUTIPCOPY_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), false, chcore::eOperation_Copy)); + bAddedAnyOption = true; + } - pCommand[0].uiCommandID=CSharedConfigStruct::DD_COPY_FLAG; - pCommand[0].eOperationType = chcore::eOperation_Copy; - GetResManager().LoadStringCopy(IDS_MENUCOPY_STRING, pCommand[0].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPY_STRING, pCommand[0].szDesc, 128); - - pCommand[1].uiCommandID=CSharedConfigStruct::DD_MOVE_FLAG; - pCommand[1].eOperationType = chcore::eOperation_Move; - GetResManager().LoadStringCopy(IDS_MENUMOVE_STRING, pCommand[1].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPMOVE_STRING, pCommand[1].szDesc, 128); - - pCommand[2].uiCommandID=CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG; - pCommand[2].eOperationType = chcore::eOperation_Copy; - GetResManager().LoadStringCopy(IDS_MENUCOPYMOVESPECIAL_STRING, pCommand[2].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPYMOVESPECIAL_STRING, pCommand[2].szDesc, 128); + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUMOVE_STRING), GetResManager().LoadString(IDS_MENUTIPMOVE_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), false, chcore::eOperation_Move)); + bAddedAnyOption = true; + } + + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPYMOVESPECIAL_STRING), GetResManager().LoadString(IDS_MENUTIPCOPYMOVESPECIAL_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeIDataObject), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializePidlFolder, chcore::TSmartPath()), true)); + bAddedAnyOption = true; + } + + if(bAddedAnyOption) + { + // insert separator as an addition to other items + spRootItem->AddChild(boost::make_shared()); + } } break; - case GC_EXPLORER: + case eLocation_ContextMenu: { - g_pscsShared->iCommandCount=5; - g_pscsShared->uiFlags |= (GetPropValue(rConfig) ? CSharedConfigStruct::EC_PASTE_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_PASTESPECIAL_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_COPYTO_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_MOVETO_FLAG : 0) - | (GetPropValue(rConfig) ? CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG : 0); - - pCommand[0].uiCommandID=CSharedConfigStruct::EC_PASTE_FLAG; - pCommand[0].eOperationType = chcore::eOperation_Copy; - GetResManager().LoadStringCopy(IDS_MENUPASTE_STRING, pCommand[0].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPPASTE_STRING, pCommand[0].szDesc, 128); - pCommand[1].uiCommandID=CSharedConfigStruct::EC_PASTESPECIAL_FLAG; - pCommand[1].eOperationType = chcore::eOperation_Copy; - GetResManager().LoadStringCopy(IDS_MENUPASTESPECIAL_STRING, pCommand[1].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPPASTESPECIAL_STRING, pCommand[1].szDesc, 128); - pCommand[2].uiCommandID=CSharedConfigStruct::EC_COPYTO_FLAG; - pCommand[2].eOperationType = chcore::eOperation_Copy; - GetResManager().LoadStringCopy(IDS_MENUCOPYTO_STRING, pCommand[2].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPYTO_STRING, pCommand[2].szDesc, 128); - pCommand[3].uiCommandID=CSharedConfigStruct::EC_MOVETO_FLAG; - pCommand[3].eOperationType = chcore::eOperation_Move; - GetResManager().LoadStringCopy(IDS_MENUMOVETO_STRING, pCommand[3].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPMOVETO_STRING, pCommand[3].szDesc, 128); - pCommand[4].uiCommandID=CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG; - pCommand[4].eOperationType = chcore::eOperation_Copy; - GetResManager().LoadStringCopy(IDS_MENUCOPYMOVETOSPECIAL_STRING, pCommand[4].szCommand, 128); - GetResManager().LoadStringCopy(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING, pCommand[4].szDesc, 128); - - // prepare shortcuts - std::vector cvShortcuts; - GetPropValue(rConfig, cvShortcuts); + if(GetPropValue(rConfig)) + { + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUPASTE_STRING), GetResManager().LoadString(IDS_MENUTIPPASTE_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), false)); + } - // count of shortcuts to store - g_pscsShared->iShortcutsCount = boost::numeric_cast(std::min(cvShortcuts.size(), (SHARED_BUFFERSIZE - 5 * sizeof(_COMMAND)) / sizeof(_SHORTCUT))); - _SHORTCUT* pShortcut = g_pscsShared->GetShortcutsPtr(); - CShortcut sc; - for (int i=0;iiShortcutsCount;i++) + if(GetPropValue(rConfig)) { - sc=CString(cvShortcuts.at(i)); - _tcsncpy(pShortcut[i].szName, sc.m_strName, 128); - _tcsncpy(pShortcut[i].szPath, sc.m_strPath, _MAX_PATH); + spRootItem->AddChild(boost::make_shared(GetResManager().LoadString(IDS_MENUPASTESPECIAL_STRING), GetResManager().LoadString(IDS_MENUTIPPASTESPECIAL_STRING), + TOperationTypeInfo(TOperationTypeInfo::eOpType_Autodetect, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_Clipboard), + TDestinationPathInfo(TDestinationPathInfo::eDstType_InitializeAuto, chcore::TSmartPath()), false)); } + + if(GetPropValue(rConfig) || GetPropValue(rConfig) || GetPropValue(rConfig)) + { + // prepare shortcuts for all menu options + std::vector vShortcutStrings; + GetPropValue(rConfig, vShortcutStrings); + + bool bRetrieveFreeSpace = GetPropValue(rConfig); + + std::vector vShortcuts; + const size_t stSizeBufferSize = 64; + boost::shared_array spSizeBuffer(new wchar_t[stSizeBufferSize]); + + BOOST_FOREACH(const CString& strShortcutString, vShortcutStrings) + { + CShortcut tShortcut; + if(tShortcut.FromString(strShortcutString)) + { + unsigned long long ullSize = 0; + + // retrieving free space might fail, but it's not critical - we just won't show the free space + if(bRetrieveFreeSpace && GetDynamicFreeSpace(tShortcut.m_strPath, &ullSize, NULL)) + { + CString strNameFormat; + strNameFormat.Format(_T("%s (%s)"), tShortcut.m_strName, GetSizeString(ullSize, spSizeBuffer.get(), stSizeBufferSize)); + + tShortcut.m_strName = strNameFormat; + } + + vShortcuts.push_back(tShortcut); + } + else + BOOST_ASSERT(false); // non-critical, but not very nice + } + + if(GetPropValue(rConfig)) + { + boost::shared_ptr menuItem(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPYTO_STRING), GetResManager().LoadString(IDS_MENUTIPCOPYTO_STRING))); + BOOST_FOREACH(const CShortcut& tShortcut, vShortcuts) + { + menuItem->AddChild(boost::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), false)); + } + + spRootItem->AddChild(menuItem); + } + + if(GetPropValue(rConfig)) + { + boost::shared_ptr menuItem(boost::make_shared(GetResManager().LoadString(IDS_MENUMOVETO_STRING), GetResManager().LoadString(IDS_MENUTIPMOVETO_STRING))); + BOOST_FOREACH(const CShortcut& tShortcut, vShortcuts) + { + menuItem->AddChild(boost::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Move), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), false)); + } + + spRootItem->AddChild(menuItem); + } + + if(GetPropValue(rConfig)) + { + boost::shared_ptr menuItem(boost::make_shared(GetResManager().LoadString(IDS_MENUCOPYMOVETOSPECIAL_STRING), GetResManager().LoadString(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING))); + BOOST_FOREACH(const CShortcut& tShortcut, vShortcuts) + { + menuItem->AddChild(boost::make_shared((PCTSTR)tShortcut.m_strName, (PCTSTR)tShortcut.m_strPath, + TOperationTypeInfo(TOperationTypeInfo::eOpType_Specified, chcore::eOperation_Copy), + TSourcePathsInfo(TSourcePathsInfo::eSrcType_InitializeAuto), + TDestinationPathInfo(TDestinationPathInfo::eDstType_Specified, chcore::PathFromString((PCTSTR)tShortcut.m_strPath)), true)); + } + + spRootItem->AddChild(menuItem); + } + } } + break; default: - ASSERT(false); // what's happening ? + ASSERT(false); // unhandled case } + + chcore::TConfig cfgStorage; + chcore::TWStringData wstrData; + + cfgShellExt.StoreInConfig(cfgStorage, _T("ShellExtCfg")); + cfgStorage.WriteToString(wstrData); + + std::wstring strSHMName = IPCSupport::GenerateSHMName((unsigned long)lParam); + + m_tCHExtharedMemory.Create(strSHMName.c_str(), wstrData); } break; Index: src/ch/MainWnd.h =================================================================== diff -u -N -r3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/MainWnd.h (.../MainWnd.h) (revision 3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f) +++ src/ch/MainWnd.h (.../MainWnd.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -23,6 +23,7 @@ #include "TrayIcon.h" #include "structs.h" #include "task.h" +#include "..\libchcore\TSharedMemory.h" class CMiniViewDlg; class CStatusDlg; @@ -41,6 +42,7 @@ CTaskArray m_tasks; chcore::IFeedbackHandlerFactory* m_pFeedbackFactory; + chcore::TSharedMemory m_tCHExtharedMemory; CMiniViewDlg* m_pdlgMiniView; CStatusDlg* m_pdlgStatus; Index: src/ch/TLocalFilesystem.cpp =================================================================== diff -u -N -rc282037f34325e59663c08db952110df6cfb06fb -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision c282037f34325e59663c08db952110df6cfb06fb) +++ src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -24,9 +24,9 @@ #include "TLocalFilesystem.h" #include "TAutoHandles.h" #include "FileInfo.h" -#include "..\Common\FileSupport.h" #include "DataBuffer.h" #include +#include "FileSupport.h" void TLocalFilesystem::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType) { Index: src/ch/TSubTaskCopyMove.cpp =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -28,7 +28,6 @@ #include "task.h" #include "TLocalFilesystem.h" #include "FeedbackHandler.h" -#include "..\Common\FileSupport.h" #include "Device IO.h" // assume max sectors of 4kB (for rounding) Index: src/ch/TTaskConfigTracker.cpp =================================================================== diff -u -N -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/TTaskConfigTracker.cpp (.../TTaskConfigTracker.cpp) (revision b684bec49aaaea4b89ab2e599497f4085d8698a3) +++ src/ch/TTaskConfigTracker.cpp (.../TTaskConfigTracker.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -104,7 +104,7 @@ return bModified; } -void TTaskConfigTracker::AddModified(const std::wstring& strModified) +void TTaskConfigTracker::AddModified(const chcore::TString& strModified) { ETaskOptions eOption = TTaskConfigTracker::GetOptionFromString(strModified); @@ -125,11 +125,14 @@ m_setModified.insert(setOptions.Get().begin(), setOptions.Get().end()); } -void TTaskConfigTracker::AddModified(const std::set& setModified) +void TTaskConfigTracker::AddModified(const chcore::TStringSet& setModified) { - BOOST_FOREACH(const std::wstring& strVal, setModified) + chcore::TStringSet::const_iterator iterBegin = setModified.Begin(); + chcore::TStringSet::const_iterator iterEnd = setModified.End(); + + for(; iterBegin != iterEnd; ++iterBegin) { - AddModified(strVal); + AddModified(*iterBegin); } } @@ -167,7 +170,7 @@ } } -void TTaskConfigTracker::RemoveModification(const std::wstring& strModified) +void TTaskConfigTracker::RemoveModification(const chcore::TString& strModified) { ETaskOptions eOption = TTaskConfigTracker::GetOptionFromString(strModified); RemoveModification(eOption); @@ -179,7 +182,7 @@ m_setModified.clear(); } -void TTaskConfigTracker::NotificationProc(const std::set& setModifications, void* pParam) +void TTaskConfigTracker::NotificationProc(const chcore::TStringSet& setModifications, void* pParam) { if(!pParam) THROW(_T("Invalid pointer"), 0, 0, 0); @@ -188,7 +191,7 @@ pTracker->AddModified(setModifications); } -ETaskOptions TTaskConfigTracker::GetOptionFromString(const std::wstring& strOption) +ETaskOptions TTaskConfigTracker::GetOptionFromString(const chcore::TString& strOption) { if(strOption == TaskPropData::GetPropertyName()) return eTO_UseOnlyDefaultBuffer; Index: src/ch/TTaskConfigTracker.h =================================================================== diff -u -N -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/TTaskConfigTracker.h (.../TTaskConfigTracker.h) (revision b684bec49aaaea4b89ab2e599497f4085d8698a3) +++ src/ch/TTaskConfigTracker.h (.../TTaskConfigTracker.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -48,21 +48,21 @@ bool IsModified(ETaskOptions eOption, bool bResetModificationState); bool IsModified(TOptionsSet setOptions, bool bResetModificationState); - void AddModified(const std::wstring& strModified); + void AddModified(const chcore::TString& strModified); void AddModified(ETaskOptions eModified); void AddModified(TOptionsSet setOptions); - void AddModified(const std::set& setModified); + void AddModified(const chcore::TStringSet& setModified); void AddModified(const std::set& setModified); void RemoveModification(ETaskOptions eModified); void RemoveModificationSet(TOptionsSet setOptions); - void RemoveModification(const std::wstring& strModified); + void RemoveModification(const chcore::TString& strModified); void Clear(); - static void NotificationProc(const std::set& setModifications, void* pParam); + static void NotificationProc(const chcore::TStringSet& setModifications, void* pParam); protected: - static ETaskOptions GetOptionFromString(const std::wstring& strOption); + static ETaskOptions GetOptionFromString(const chcore::TString& strOption); protected: std::set m_setModified; Index: src/ch/ch.cpp =================================================================== diff -u -N -r3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/ch.cpp (.../ch.cpp) (revision 3127f6bb39be81d3b451ffbc3d0bad7f85d4a89f) +++ src/ch/ch.cpp (.../ch.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -45,8 +45,6 @@ //}}AFX_MSG_MAP END_MESSAGE_MAP() -CSharedConfigStruct* g_pscsShared; - int iCount=98; unsigned short msg[]={ 0x40d1, 0x4dcd, 0x8327, 0x6cdf, 0xb912, 0x017b, 0xac78, 0x1e04, 0x5637, 0x1822, 0x0a69, 0x1b40, 0x4169, 0x504d, 0x80ff, 0x6c2f, 0xa612, 0x017e, @@ -78,13 +76,12 @@ theApp.OnResManNotify(uiMsg); } -void ConfigPropertyChangedCallback(const std::set& setPropNames, void* /*pParam*/) +void ConfigPropertyChangedCallback(const chcore::TStringSet& setPropNames, void* /*pParam*/) { theApp.OnConfigNotify(setPropNames); } CCopyHandlerApp::CCopyHandlerApp() : - m_hMapObject(NULL), m_pMainWindow(NULL) { // this is the one-instance application @@ -93,12 +90,6 @@ CCopyHandlerApp::~CCopyHandlerApp() { - // Unmap shared memory from the process's address space. - UnmapViewOfFile((LPVOID)g_pscsShared); - - // Close the process's handle to the file-mapping object. - CloseHandle(m_hMapObject); - if (m_pMainWindow) { ((CMainWnd*)m_pMainWindow)->DestroyWindow(); @@ -352,17 +343,6 @@ InitCommonControlsEx(&InitCtrls); // ================================= Shell extension ======================================== - LOG_INFO(_T("Initializing shared memory for communication with shell extension")); - - m_hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CSharedConfigStruct), _T("CHLMFile")); - if (m_hMapObject == NULL) - return FALSE; - - // Get a pointer to the file-mapped shared memory. - g_pscsShared=(CSharedConfigStruct*)MapViewOfFile(m_hMapObject, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - if (g_pscsShared == NULL) - return FALSE; - LOG_INFO(_T("Checking shell extension compatibility")); InitShellExtension(); @@ -511,10 +491,10 @@ } */ -void CCopyHandlerApp::OnConfigNotify(const std::set& setPropNames) +void CCopyHandlerApp::OnConfigNotify(const chcore::TStringSet& setPropNames) { // is this language - if(setPropNames.find(PropData::GetPropertyName()) != setPropNames.end()) + if(setPropNames.HasValue(PropData::GetPropertyName())) { // update language in resource manager CString strPath; @@ -523,21 +503,21 @@ strPath.ReleaseBuffer(); } - if(setPropNames.find(PropData::GetPropertyName()) != setPropNames.end()) + if(setPropNames.HasValue(PropData::GetPropertyName())) { chcore::TLogger& rLogger = chcore::TLogger::Acquire(); rLogger.Enable(GetPropValue(GetConfig())); } - if(setPropNames.find(PropData::GetPropertyName()) != setPropNames.end()) + if(setPropNames.HasValue(PropData::GetPropertyName())) { chcore::TLogger& rLogger = chcore::TLogger::Acquire(); rLogger.set_log_level(GetPropValue(GetConfig())); } - if(setPropNames.find(PropData::GetPropertyName()) != setPropNames.end()) + if(setPropNames.HasValue(PropData::GetPropertyName())) { chcore::TLogger& rLogger = chcore::TLogger::Acquire(); Index: src/ch/ch.h =================================================================== diff -u -N -r8dd3566d66a35a662872eaaa45eef5049e71c3dc -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/ch.h (.../ch.h) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) +++ src/ch/ch.h (.../ch.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -60,7 +60,7 @@ void RegisterShellExtension(); void UnregisterShellExtension(); - void OnConfigNotify(const std::set& setPropNames); + void OnConfigNotify(const chcore::TStringSet& setPropNames); void OnResManNotify(UINT uiType); const TCommandLineParser& GetCommandLine() const { return m_cmdLineParser; } @@ -72,7 +72,6 @@ void InitShellExtension(); protected: - HANDLE m_hMapObject; TShellExtensionClient m_tShellExtClient; TCommandLineParser m_cmdLineParser; Index: src/ch/ch.vc90.vcproj =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -387,22 +387,26 @@ Name="Shared" > + + @@ -623,6 +627,14 @@ > + + + + Index: src/ch/task.cpp =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/task.cpp (.../task.cpp) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/task.cpp (.../task.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -25,7 +25,6 @@ #include #include "StringHelpers.h" -#include "../common/FileSupport.h" #include "FeedbackHandler.h" #include "TTaskConfiguration.h" @@ -35,6 +34,7 @@ #include "TSubTaskScanDirectory.h" #include "TSubTaskCopyMove.h" #include "TSubTaskDelete.h" +#include "FileSupport.h" //////////////////////////////////////////////////////////////////////////// // CTask members @@ -207,7 +207,7 @@ if(m_strFilePath.IsEmpty()) { boost::upgrade_to_unique_lock upgraded_lock(lock); - m_strFilePath = m_strTaskDirectory + m_tTaskDefinition.GetTaskUniqueID().c_str() + _T(".cht"); + m_strFilePath = m_strTaskDirectory + m_tTaskDefinition.GetTaskUniqueID() + _T(".cht"); } // store task definition only if changed @@ -389,7 +389,7 @@ pData->m_ullProcessedSize = m_localStats.GetProcessedSize(); pData->m_stSize=m_files.GetSize(); pData->m_ullSizeAll = m_localStats.GetTotalSize(); - pData->m_strUniqueName = m_tTaskDefinition.GetTaskUniqueID().c_str(); + pData->m_strUniqueName = m_tTaskDefinition.GetTaskUniqueID(); pData->m_eOperationType = m_tTaskDefinition.GetOperationType(); pData->m_eSubOperationType = m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(m_tTaskBasicProgressInfo.GetSubOperationIndex()); @@ -890,7 +890,7 @@ // in all cases we would like to have task definition path defined CString strFilePath = m_strFilePath; if(strFilePath.IsEmpty()) - strFilePath = m_strTaskDirectory + m_tTaskDefinition.GetTaskUniqueID().c_str() + _T(".cht"); + strFilePath = m_strTaskDirectory + m_tTaskDefinition.GetTaskUniqueID() + _T(".cht"); switch(ePathType) { @@ -911,13 +911,13 @@ } } -void CTask::OnCfgOptionChanged(const std::set& rsetChanges, void* pParam) +void CTask::OnCfgOptionChanged(const chcore::TStringSet& rsetChanges, void* pParam) { CTask* pTask = (CTask*)pParam; if(!pTask) THROW(_T("Invalid pointer"), 0, 0, 0); - if(rsetChanges.find(TaskPropData::GetPropertyName()) != rsetChanges.end()) + if(rsetChanges.HasValue(TaskPropData::GetPropertyName())) { pTask->m_workerThread.ChangePriority(GetTaskPropValue(pTask->GetTaskDefinition().GetConfiguration())); } Index: src/ch/task.h =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/ch/task.h (.../task.h) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/task.h (.../task.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -206,7 +206,7 @@ CString GetRelatedPathNL(EPathType ePathType); - static void OnCfgOptionChanged(const std::set& rsetChanges, void* pParam); + static void OnCfgOptionChanged(const chcore::TStringSet& rsetChanges, void* pParam); private: // task initial information (needed to start a task); might be a bit processed. Index: src/chext/ActionSelector.cpp =================================================================== diff -u -N --- src/chext/ActionSelector.cpp (revision 68739164e349c34dcd0bcb36c6eb381f23cb8b77) +++ src/chext/ActionSelector.cpp (revision 0) @@ -1,221 +0,0 @@ -// ============================================================================ -// Copyright (C) 2001-2008 by Jozef Starosczyk -// ixen@copyhandler.com -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License -// (version 2) as published by the Free Software Foundation; -// -// 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 Library General Public -// License along with this program; if not, write to the -// Free Software Foundation, Inc., -// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// ============================================================================ -/// @file ActionSelector.cpp -/// @brief Implementation of TActionSelector. -// ============================================================================ -#include "stdafx.h" -#include "ActionSelector.h" - -// ============================================================================ -/// TActionSelector::TActionSelector -/// @date 2009/03/12 -/// -/// @brief Constructs the action selector object. -// ============================================================================ -TActionSelector::TActionSelector() : - m_ulKeysState(eKey_None), - m_ulPreferredDropEffect(0), - m_eDefaultOperation(eAction_None), - m_eDefaultMenuItem(eAction_None), - m_ulActionOptions(eOption_None) -{ -} - -// ============================================================================ -/// TActionSelector::~TActionSelector -/// @date 2009/03/12 -/// -/// @brief Destructs the action selection object. -// ============================================================================ -TActionSelector::~TActionSelector() -{ -} - -// ============================================================================ -/// TActionSelector::ResetState -/// @date 2009/03/12 -/// -/// @brief Resets the state contained in this class. -// ============================================================================ -void TActionSelector::ResetState() -{ - m_ulKeysState = eKey_None; - m_ulPreferredDropEffect = 0; - m_eDefaultOperation = eAction_None; - m_eDefaultMenuItem = eAction_None; - m_ulActionOptions = eOption_None; -} - -// ============================================================================ -/// TActionSelector::ReadKeysState -/// @date 2009/03/12 -/// -/// @brief Retrieves the keyboard state at a time of call. -// ============================================================================ -void TActionSelector::ReadKeyboardState() -{ - m_ulKeysState = ((GetKeyState(VK_SHIFT) & 0x80) ? eKey_Shift : 0) | - ((GetKeyState(VK_CONTROL) & 0x80) ? eKey_Ctrl : 0) | - ((GetKeyState(VK_MENU) & 0x80) ? eKey_Alt : 0); -} - -// ============================================================================ -/// TActionSelector::ReadStateFromDataObject -/// @date 2009/03/12 -/// -/// @brief Retrieves the state from data object. -/// @param[in] piDataObject Data object to retrieve the information from. -/// @param[in] pszDestinationPath Destination path for the operation (used with simple heuristics). -/// @return Result of the operation. -// ============================================================================ -HRESULT TActionSelector::ReadStateFromDataObject(IDataObject* piDataObject, PCTSTR pszDestinationPath) -{ - if(!piDataObject || !pszDestinationPath || pszDestinationPath[0] == _T('\0')) - return E_INVALIDARG; - - // try to retrieve the preferred drop effect from the input data object - UINT uiPreferredDropEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); - if(!uiPreferredDropEffect) - return E_FAIL; - - FORMATETC fe = { (CLIPFORMAT)uiPreferredDropEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - STGMEDIUM medium; - - // if the drop effect does not exist - just report it - m_ulPreferredDropEffect = 0; - HRESULT hResult = piDataObject->QueryGetData(&fe); - if(hResult == S_OK) - { - hResult = piDataObject->GetData(&fe, &medium); - if(SUCCEEDED(hResult) && !medium.hGlobal) - { - ReleaseStgMedium(&medium); - hResult = E_FAIL; - } - if(SUCCEEDED(hResult)) - { - // specify operation - DWORD* pdwData = (DWORD*)GlobalLock(medium.hGlobal); - if(pdwData) - { - m_ulPreferredDropEffect = *pdwData; - GlobalUnlock(medium.hGlobal); - } - else - hResult = E_FAIL; - ReleaseStgMedium(&medium); - } - } - - // now try to get into the CF_HDROP information and use a simple heuristic to determine operation - m_eDefaultOperation = eAction_None; - fe.cfFormat = CF_HDROP; - - // are the data available? - hResult = piDataObject->QueryGetData(&fe); - if(hResult != S_OK) - return S_FALSE; - - hResult = piDataObject->GetData(&fe, &medium); - if(SUCCEEDED(hResult) && !medium.hGlobal) - { - ReleaseStgMedium(&medium); - hResult = E_FAIL; - } - if(SUCCEEDED(hResult)) - { - // copy is the default - m_eDefaultOperation = eAction_Copy; - - // autodetecting - copy or move - check the last path - UINT uiCount = DragQueryFile((HDROP)medium.hGlobal, 0xffffffff, NULL, 0); - TCHAR szPath[_MAX_PATH]; - if(DragQueryFile((HDROP)medium.hGlobal, uiCount - 1, szPath, _MAX_PATH)) - { - // check if the path has some common elements with destination paths - if(_tcsncmp(szPath, _T("\\\\"), 2) == 0) - { - TCHAR* pFnd = _tcsstr(szPath+2, _T("\\")); - if(pFnd) - { - size_t stCount; - // find another - TCHAR *pSecond = _tcsstr(pFnd + 1, _T("\\")); - if(pSecond) - stCount = pSecond - szPath; - else - stCount = _tcslen(szPath); - - // found - compare - if(_tcsnicmp(szPath, pszDestinationPath, stCount) == 0) - m_eDefaultOperation = eAction_Move; - } - } - else if(pszDestinationPath[0] == szPath[0]) // when processing within the same disk drive - we move by default - m_eDefaultOperation = eAction_Move; - } - - ReleaseStgMedium(&medium); - } - - return hResult; -} - -// ============================================================================ -/// TActionSelector::ReadStateFromMenu -/// @date 2009/03/12 -/// -/// @brief Reads the state from menu handle. -/// @param[in] hMenu Handle to a menu containing basic items. -// ============================================================================ -void TActionSelector::ReadStateFromMenu(HMENU hMenu) -{ - // it's none by default - m_eDefaultMenuItem = eAction_None; - - _ASSERTE(hMenu != NULL); - if(!hMenu) - return; - - MENUITEMINFO mii; - mii.cbSize = sizeof(MENUITEMINFO); - mii.fMask = MIIM_STATE; - - if(::GetMenuItemInfo(hMenu, 1, FALSE, &mii) && mii.fState & MFS_DEFAULT) - m_eDefaultMenuItem = eAction_Copy; - if(::GetMenuItemInfo(hMenu, 2, FALSE, &mii) && mii.fState & MFS_DEFAULT) - m_eDefaultMenuItem = eAction_Move; - if(::GetMenuItemInfo(hMenu, 3, FALSE, &mii) && mii.fState & MFS_DEFAULT) - m_eDefaultMenuItem = eAction_Shortcut; -} - -// ============================================================================ -/// TActionSelector::GetActionSource -/// @date 2009/03/12 -/// -/// @brief Calculates the action source based on the state collected so far. -/// @return Combination of eSrc_* with eAction_* -// ============================================================================ -ulong_t TActionSelector::GetActionSource() -{ - unsigned long ulSrc = (m_ulPreferredDropEffect != 0) ? (m_ulKeysState != eKey_None ? eSrc_Keyboard : eSrc_CtxMenu) : eSrc_DropMenu; - unsigned long ulAction = m_eDefaultMenuItem != eAction_None ? m_eDefaultMenuItem : m_eDefaultOperation; - - return ulSrc | ulAction; -} Index: src/chext/ActionSelector.h =================================================================== diff -u -N --- src/chext/ActionSelector.h (revision 0373359eff650e8cf04a5992711ef9f20347536f) +++ src/chext/ActionSelector.h (revision 0) @@ -1,91 +0,0 @@ -// ============================================================================ -// Copyright (C) 2001-2009 by Jozef Starosczyk -// ixen@copyhandler.com -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License -// (version 2) as published by the Free Software Foundation; -// -// 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 Library General Public -// License along with this program; if not, write to the -// Free Software Foundation, Inc., -// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// ============================================================================ -/// @file ActionSelector.h -/// @date 2009/03/12 -/// @brief Contains a class handling the action selection for drag&drop menu. -// ============================================================================ -#ifndef __ACTIONSELECTOR_H__ -#define __ACTIONSELECTOR_H__ - -class TActionSelector -{ -public: - /// State of the keyboard - enum EStateKeys - { - eKey_None = 0, - eKey_Ctrl = 1, - eKey_Alt = 2, - eKey_Shift = 4 - }; - - /// Default operation - enum EAction - { - eAction_None = 0x0000, - eAction_Copy = 0x0001, - eAction_Move = 0x0002, - eAction_Shortcut = 0x0004 - }; - - enum EActionSource - { - eSrc_None = 0x0000, - eSrc_CtxMenu = 0x0100, - eSrc_DropMenu = 0x0200, - eSrc_Keyboard = 0x0400, - }; - - enum EActionOptions - { - eOption_None = 0x0000, ///< No integration at all - eOption_BasicIntegration = 0x0001, ///< Basic integration (CH menu items, no override) - eOption_DragAndDropOverride = 0x0002, ///< Intercepts drag&drop operation using the left mouse button - eOption_KeyboardOverride = 0x0004 ///< Intercepts Ctrl+V operation - }; - -public: - TActionSelector(); - ~TActionSelector(); - - /// Reads current keyboard state - void ReadKeyboardState(); - /// Retrieves all informations available in IDataObject related to the action selection process - HRESULT ReadStateFromDataObject(IDataObject* piDataObject, PCTSTR pszDestinationPath); - /// Retrieves the state information from a menu handle - void ReadStateFromMenu(HMENU hMenu); - - /// Retrieves the action source using the - ulong_t GetActionSource(); - - /// Sets the action options (EActionOptions) - void SetActionOptions(ulong_t ulOptions) { m_ulActionOptions = ulOptions; } - - /// Resets all states - void ResetState(); - -protected: - ulong_t m_ulKeysState; ///< State of the ctrl/shift/alt keys - ulong_t m_ulPreferredDropEffect; ///< Preferred drop effect from IDataObject - EAction m_eDefaultOperation; ///< Default operation determined from IDataObject (detected with simple heuristics) - EAction m_eDefaultMenuItem; ///< Default operation retrieved using the menu handle - unsigned long m_ulActionOptions; ///< Options determining the final action to be performed -}; - -#endif Index: src/chext/DropMenuExt.cpp =================================================================== diff -u -N -r3d1951f52696fe21e01618e1bbfb9e14745a3827 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 3d1951f52696fe21e01618e1bbfb9e14745a3827) +++ src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -25,12 +25,12 @@ #include #include "ShellPathsHelpers.h" #include "../libchcore/TWStringData.h" +#include "../common/TShellExtMenuConfig.h" +#include "../libchcore/TSharedMemory.h" ///////////////////////////////////////////////////////////////////////////// // CDropMenuExt -extern CSharedConfigStruct* g_pscsShared; - CDropMenuExt::CDropMenuExt() : m_piShellExtControl(NULL) { @@ -48,25 +48,23 @@ STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) { + ATLTRACE(_T("[CDropMenuExt::Initialize] CDropMenuExt::Initialize()\n")); + + // When called: + // 1. R-click on a directory + // 2. R-click on a directory background + // 3. Pressed Ctrl+C, Ctrl+X on a specified file/directory + if(!pidlFolder && !piDataObject) return E_FAIL; if(!pidlFolder || !piDataObject) _ASSERTE(!_T("Missing at least one parameter - it's unexpected.")); - // When called: - // 1. R-click on a directory - // 2. R-click on a directory background - // 3. Pressed Ctrl+C, Ctrl+X on a specified file/directory - ATLTRACE(_T("[CDropMenuExt::Initialize] CDropMenuExt::Initialize()\n")); if(!piDataObject) return E_FAIL; - // remember the keyboard state for later - m_asSelector.ResetState(); - m_asSelector.ReadKeyboardState(); - - // check if this extension is enabled + // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) return hResult; @@ -76,25 +74,42 @@ if(hWnd == NULL) return E_FAIL; - // retrieve config from CH - ::SendMessage(hWnd, WM_GETCONFIG, GC_DRAGDROP, 0); + hResult = ReadShellConfig(); + if(SUCCEEDED(hResult)) + hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); - m_vPaths.Clear(); - m_pathPidl.Clear(); + return hResult; +} - // get dest folder - if(pidlFolder) - hResult = ShellPathsHelpers::GetPathFromITEMIDLIST(pidlFolder, m_pathPidl); - // now retrieve the preferred drop effect from IDataObject - if(SUCCEEDED(hResult)) - hResult = m_asSelector.ReadStateFromDataObject(piDataObject, m_pathPidl.ToString()); +STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) +{ + ATLTRACE(_T("CDropMenuExt::QueryContextMenu()\n")); - if(SUCCEEDED(hResult)) - hResult = ShellPathsHelpers::GetPathsFromIDataObject(piDataObject, m_vPaths); + // check options + HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + return hResult; - ATLTRACE(_T("[CDropMenuExt::Initialize] Exit hResult == 0x%lx\n"), hResult); + // find CH's window + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(!hWnd) + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); - return hResult; + // retrieve the default menu item; if not available, fallback to the default heuristics + m_tShellExtData.ReadDefaultSelectionStateFromMenu(hMenu); + + // retrieve the action information to be performed + TShellExtData::EActionSource eActionSource = m_tShellExtData.GetActionSource(); + + // determine if we want to perform override based on user options and detected action source + bool bIntercept = (m_tShellExtMenuConfig.GetInterceptDragAndDrop() && eActionSource == TShellExtData::eSrc_DropMenu || + m_tShellExtMenuConfig.GetInterceptKeyboardActions() && eActionSource == TShellExtData::eSrc_Keyboard || + m_tShellExtMenuConfig.GetInterceptCtxMenuActions() && eActionSource == TShellExtData::eSrc_CtxMenu); + + TShellMenuItemPtr spRootMenuItem = m_tShellExtMenuConfig.GetCommandRoot(); + m_tContextMenuHandler.Init(spRootMenuItem, hMenu, idCmdFirst, indexMenu, m_tShellExtData, m_tShellExtMenuConfig.GetShowShortcutIcons(), bIntercept); + + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, m_tContextMenuHandler.GetLastCommandID() - idCmdFirst + 1); } STDMETHODIMP CDropMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) @@ -109,183 +124,88 @@ if(hWnd == NULL) return E_FAIL; - // commands - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - if(!pCommand) + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpici->lpVerb)); + if(!spSelectedItem) return E_FAIL; - // set the operation type - chcore::TTaskDefinition tTaskDefinition; - tTaskDefinition.SetSourcePaths(m_vPaths); - tTaskDefinition.SetDestinationPath(m_pathPidl); - tTaskDefinition.SetOperationType(pCommand[LOWORD(lpici->lpVerb)].eOperationType); + // data retrieval and validation + if(!m_tShellExtData.VerifyItemCanBeExecuted(spSelectedItem)) + return E_FAIL; - // get the gathered data as XML - chcore::TWStringData wstrXML; - tTaskDefinition.StoreInString(wstrXML); + chcore::TPathContainer vSourcePaths; + chcore::TSmartPath spDestinationPath; + chcore::EOperationType eOperationType = chcore::eOperation_None; -// ::MessageBox(NULL, wstrXML.GetData(), _T("DropMenuExt.cpp / Copy/Move to [special]"), MB_OK); // TEMP - to be removed before commit + if(!m_tShellExtData.GetSourcePathsByItem(spSelectedItem, vSourcePaths)) + return E_FAIL; + if(!m_tShellExtData.GetDestinationPathByItem(spSelectedItem, spDestinationPath)) + return E_FAIL; + if(!m_tShellExtData.GetOperationTypeByItem(spSelectedItem, eOperationType)) + return E_FAIL; - // IPC struct - COPYDATASTRUCT cds; - switch(pCommand[LOWORD(lpici->lpVerb)].uiCommandID) - { - case CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG: - cds.dwData = eCDType_TaskDefinitionContentSpecial; - break; - default: - cds.dwData = eCDType_TaskDefinitionContent; - } + chcore::TTaskDefinition tTaskDefinition; + tTaskDefinition.SetSourcePaths(vSourcePaths); + tTaskDefinition.SetDestinationPath(spDestinationPath); + tTaskDefinition.SetOperationType(eOperationType); - cds.cbData = (DWORD)wstrXML.GetBytesCount(); - cds.lpData = (void*)wstrXML.GetData(); + // get task data as xml + chcore::TWStringData wstrData; + tTaskDefinition.StoreInString(wstrData); - // send a message to ch + // fill struct + COPYDATASTRUCT cds; + cds.dwData = spSelectedItem->IsSpecialOperation() ? eCDType_TaskDefinitionContentSpecial : eCDType_TaskDefinitionContent; + cds.lpData = (void*)wstrData.GetData(); + cds.cbData = (DWORD)wstrData.GetBytesCount(); + + // send a message ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); return S_OK; } -STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) +STDMETHODIMP CDropMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) { - ATLTRACE(_T("CDropMenuExt::QueryContextMenu()\n")); - // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; + memset(pszName, 0, cchMax); - // find CH's window - HWND hWnd; - hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if(!hWnd) - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); + if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) + return S_OK; - // retrieve the default menu item; if not available, fallback to the default heuristics - m_asSelector.ReadStateFromMenu(hmenu); - - // retrieve the action information to be performed - ulong_t ulActionSource = m_asSelector.GetActionSource(); - - // determine if we want to perform override based on user options and detected action source - bool bIntercept = (g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptDragAndDrop && ulActionSource & TActionSelector::eSrc_DropMenu || - g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptKeyboardActions && ulActionSource & TActionSelector::eSrc_Keyboard || - g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptCtxMenuActions && ulActionSource & TActionSelector::eSrc_CtxMenu); - - // now convert our information to the - // got a config - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - int iCommandCount=0; - - // ad new menu items, depending on the received configuration - if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_COPY_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+0, pCommand[0].szCommand); - if(bIntercept && ulActionSource & TActionSelector::eAction_Copy) - ::SetMenuDefaultItem(hmenu, idCmdFirst+0, FALSE); - iCommandCount++; - } - - if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_MOVE_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+1, pCommand[1].szCommand); - if(bIntercept && ulActionSource & TActionSelector::eAction_Move) - ::SetMenuDefaultItem(hmenu, idCmdFirst+1, FALSE); - iCommandCount++; - } - - if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+2, pCommand[2].szCommand); -/* - if(g_pscsShared->bOverrideDefault && m_eDropEffect == eEffect_Special) - ::SetMenuDefaultItem(hmenu, idCmdFirst+2, FALSE); -*/ - iCommandCount++; - } - - if(iCommandCount) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_SEPARATOR, idCmdFirst+3, NULL); - iCommandCount++; - } - - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 4); -} - -STDMETHODIMP CDropMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) -{ // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - { - pszName[0] = _T('\0'); + if(FAILED(hResult)) return hResult; - } + else if(hResult == S_FALSE) + return S_OK; - if(uFlags == GCS_HELPTEXTW) - { - USES_CONVERSION; + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(idCmd)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; - // find CH's window - HWND hWnd; - hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if(hWnd) + switch(uFlags) + { + case GCS_HELPTEXTW: { - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - - switch (idCmd) - { - case 0: - case 1: - case 2: - { - CT2W ct2w(pCommand[idCmd].szDesc); - wcsncpy(reinterpret_cast(pszName), ct2w, cchMax); - break; - } - default: - wcsncpy(reinterpret_cast(pszName), L"", cchMax); - break; - } + wcsncpy(reinterpret_cast(pszName), spSelectedItem->GetItemTip(), spSelectedItem->GetItemTip().GetLength() + 1); + break; } - else - wcsncpy(reinterpret_cast(pszName), L"", cchMax); - } - if(uFlags == GCS_HELPTEXTA) - { - // find CH's window - HWND hWnd; - hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - - if(hWnd) + case GCS_HELPTEXTA: { - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - - switch (idCmd) - { - case 0: - case 1: - case 2: - { - CT2A ct2a(pCommand[idCmd].szDesc); - strncpy(pszName, ct2a, cchMax); - break; - } - default: - strncpy(pszName, "", cchMax); - break; - } + USES_CONVERSION; + CT2A ct2a(spSelectedItem->GetItemTip()); + strncpy(reinterpret_cast(pszName), ct2a, strlen(ct2a) + 1); + break; } - else - strncpy(pszName, "", cchMax); } return S_OK; } STDMETHODIMP CDropMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { - return HandleMenuMsg2(uMsg, wParam, lParam, NULL); + uMsg; wParam; lParam; + return S_FALSE; } STDMETHODIMP CDropMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* /*plResult*/) @@ -294,3 +214,36 @@ ATLTRACE(_T("CDropMenuExt::HandleMenuMsg2(): uMsg = %lu, wParam = %lu, lParam = %lu\n"), uMsg, wParam, lParam); return S_FALSE; } + +HRESULT CDropMenuExt::ReadShellConfig() +{ + try + { + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(hWnd == NULL) + return E_FAIL; + + // get cfg from ch + unsigned long ulSHMID = GetTickCount(); + ::SendMessage(hWnd, WM_GETCONFIG, eLocation_DragAndDropMenu, ulSHMID); + + std::wstring strSHMName = IPCSupport::GenerateSHMName(ulSHMID); + + chcore::TSharedMemory tSharedMemory; + chcore::TWStringData wstrData; + chcore::TConfig cfgShellExtData; + + tSharedMemory.Open(strSHMName.c_str()); + tSharedMemory.Read(wstrData); + + cfgShellExtData.ReadFromString(wstrData); + + m_tShellExtMenuConfig.ReadFromConfig(cfgShellExtData, _T("ShellExtCfg")); + + return S_OK; + } + catch(...) + { + return E_FAIL; + } +} Index: src/chext/DropMenuExt.h =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/chext/DropMenuExt.h (.../DropMenuExt.h) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/chext/DropMenuExt.h (.../DropMenuExt.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -20,10 +20,10 @@ #define __DROPMENUEXT_H_ #include "resource.h" // main symbols -#include "ActionSelector.h" +#include "TContextMenuHandler.h" +#include "..\common\TShellExtMenuConfig.h" +#include "TShellExtData.h" -#include "../libchcore/TTaskDefinition.h" - ///////////////////////////////////////////////////////////////////////////// // CDropMenuExt class ATL_NO_VTABLE CDropMenuExt : @@ -56,9 +56,18 @@ STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult); protected: + HRESULT ReadShellConfig(); + +protected: IShellExtControl* m_piShellExtControl; - TActionSelector m_asSelector; + TShellExtData m_tShellExtData; + TShellExtMenuConfig m_tShellExtMenuConfig; + + TContextMenuHandler m_tContextMenuHandler; + +// TActionSelector m_asSelector; + chcore::TPathContainer m_vPaths; chcore::TSmartPath m_pathPidl; }; Index: src/chext/MenuExt.cpp =================================================================== diff -u -N -r3d1951f52696fe21e01618e1bbfb9e14745a3827 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision 3d1951f52696fe21e01618e1bbfb9e14745a3827) +++ src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -20,19 +20,19 @@ #include "chext.h" #include "MenuExt.h" #include "..\common\ipcstructs.h" -#include "..\common\FileSupport.h" #include "stdio.h" #include "memory.h" -#include "StringHelpers.h" #include "chext-utils.h" #include #include "ShellPathsHelpers.h" #include "../libchcore/TWStringData.h" +#include "../common/TShellExtMenuConfig.h" +#include "../libchcore/TSharedMemory.h" +#include "../libchcore/TTaskDefinition.h" +#include -extern CSharedConfigStruct* g_pscsShared; - // globals -void CutAmpersands(LPTSTR lpszString) +static void CutAmpersands(LPTSTR lpszString) { int iOffset=0; size_t iLength=_tcslen(lpszString); @@ -77,209 +77,35 @@ return hResult; // find ch window + // find ch window HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if(hWnd == NULL) - return E_FAIL; + if(!hWnd) + return S_OK; - // get cfg from ch - ::SendMessage(hWnd, WM_GETCONFIG, GC_EXPLORER, 0); + hResult = ReadShellConfig(); + if(SUCCEEDED(hResult)) + hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); - // background or folder ? - m_bBackground = (piDataObject == NULL) && (pidlFolder != NULL); - - // get data from IDataObject - files to copy/move - m_bShowPasteOption = true; - - m_vPaths.Clear(); - - if(piDataObject) - { - hResult = ShellPathsHelpers::GetPathsFromIDataObject(piDataObject, m_vPaths); - if(hResult != S_OK) - return E_FAIL; - } - else if(pidlFolder) - { - chcore::TSmartPath pathFromPIDL; - hResult = ShellPathsHelpers::GetPathFromITEMIDLIST(pidlFolder, pathFromPIDL); - if(SUCCEEDED(hResult) && !pathFromPIDL.IsEmpty()) - m_vPaths.Add(pathFromPIDL); - } - else - _ASSERTE(!_T("Both pidlFolder and piDataObject specified. Report this unsupported situation.")); - - // find the first non-empty entry - m_bShowPasteOption = (m_vPaths.GetCount() == 1) && (::GetFileAttributes(m_vPaths.GetAt(0).ToString()) & FILE_ATTRIBUTE_DIRECTORY); - - return S_OK; + return hResult; } -STDMETHODIMP CMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) +STDMETHODIMP CMenuExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { - ATLTRACE(_T("CMenuExt::InvokeCommand()\n")); + ATLTRACE(_T("CMenuExt::QueryContextMenu()\n")); // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) - return E_FAIL; // required to process other InvokeCommand handlers. - - // find window - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if(hWnd == NULL) - return E_FAIL; - - // commands - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - - // command type - switch(LOWORD(lpici->lpVerb)) - { - // paste & paste special - case 0: - case 1: - { - // paste and paste special requires a single directory path inside m_vPaths - if((m_vPaths.GetCount() != 1) || !(::GetFileAttributes(m_vPaths.GetAt(0).ToString()) & FILE_ATTRIBUTE_DIRECTORY)) - return E_FAIL; - - // search for source paths in the clipboard - if(IsClipboardFormatAvailable(CF_HDROP)) - { - bool bMove = false; // 0-copy, 1-move - - // read paths from clipboard - OpenClipboard(lpici->hwnd); - HANDLE hClipboardData = GetClipboardData(CF_HDROP); - - chcore::TPathContainer vPaths; - ShellPathsHelpers::GetPathsFromHDROP(static_cast(hClipboardData), vPaths); - - // check if there is also a hint about operation type - UINT nFormat = RegisterClipboardFormat(_T("Preferred DropEffect")); - if(IsClipboardFormatAvailable(nFormat)) - { - hClipboardData = GetClipboardData(nFormat); - if(!hClipboardData) - return E_FAIL; - - LPVOID pClipboardData = GlobalLock(hClipboardData); - if(!pClipboardData) - return E_FAIL; - - DWORD dwData = ((DWORD*)pClipboardData)[0]; - if(dwData & DROPEFFECT_MOVE) - bMove = true; - - GlobalUnlock(hClipboardData); - } - - CloseClipboard(); - - chcore::TTaskDefinition tTaskDefinition; - tTaskDefinition.SetSourcePaths(vPaths); - tTaskDefinition.SetDestinationPath(m_vPaths.GetAt(0)); - tTaskDefinition.SetOperationType(bMove ? chcore::eOperation_Move : chcore::eOperation_Copy); - - // get task data as xml - chcore::TWStringData wstrData; - tTaskDefinition.StoreInString(wstrData); - - //::MessageBox(NULL, wstrData.GetData(), _T("MenuExt.cpp / Paste [special]"), MB_OK); // TEMP - to be removed before commit - - // fill struct - COPYDATASTRUCT cds; - - switch(pCommand[LOWORD(lpici->lpVerb)].uiCommandID) - { - case CSharedConfigStruct::EC_PASTESPECIAL_FLAG: - cds.dwData = eCDType_TaskDefinitionContentSpecial; - break; - default: - cds.dwData = eCDType_TaskDefinitionContent; - } - cds.lpData = (void*)wstrData.GetData(); - cds.cbData = (DWORD)wstrData.GetBytesCount(); - - // send a message - ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); - } - } - break; - - // case 2: - // case 3: - // case 4: - default: - { - // out of range - may be a shortcut - if(LOWORD(lpici->lpVerb) < g_pscsShared->iCommandCount + (m_bBackground ? 0 : 3 * g_pscsShared->iShortcutsCount)) - { - // pClipboardData of a table with shortcuts - _SHORTCUT* stShortcuts = g_pscsShared->GetShortcutsPtr(); - - // find command for which this command is generated - int iCommandIndex = (int)(((LOWORD(lpici->lpVerb)-5) / g_pscsShared->iShortcutsCount))+2; // command index - int iShortcutIndex = ((LOWORD(lpici->lpVerb)-5) % g_pscsShared->iShortcutsCount); // shortcut index - - chcore::TTaskDefinition tTaskDefinition; - - tTaskDefinition.SetSourcePaths(m_vPaths); - tTaskDefinition.SetDestinationPath(chcore::PathFromString(stShortcuts[iShortcutIndex].szPath)); - tTaskDefinition.SetOperationType(pCommand[iCommandIndex].eOperationType); - - // get task data as xml - chcore::TWStringData wstrData; - tTaskDefinition.StoreInString(wstrData); - -// ::MessageBox(NULL, wstrData.GetData(), _T("MenuExt.cpp / Copy/Move to [special]"), MB_OK); // TEMP - to be removed before commit - - // fill struct - COPYDATASTRUCT cds; - switch(pCommand[iCommandIndex].uiCommandID) - { - case CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG: - cds.dwData = eCDType_TaskDefinitionContentSpecial; - break; - default: - cds.dwData = eCDType_TaskDefinitionContent; - } - - cds.dwData = pCommand[iCommandIndex].uiCommandID; - cds.lpData = (void*)wstrData.GetData(); - cds.cbData = (DWORD)wstrData.GetBytesCount(); - - // send message - ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); - } - else - return E_FAIL; - } - break; - } - - return S_OK; -} - -STDMETHODIMP CMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) -{ - ATLTRACE(_T("CMenuExt::QueryContextMenu()\n")); - // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) return hResult; // find ch window - HWND hWnd; - hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); if(!hWnd) return S_OK; - // remember ID of the first command - m_uiFirstID=idCmdFirst; - // current commands count in menu TCHAR szText[_MAX_PATH]; - int iCount=::GetMenuItemCount(hmenu); + int iCount = ::GetMenuItemCount(hMenu); MENUITEMINFO mii; mii.cbSize=sizeof(mii); @@ -290,7 +116,7 @@ // find a place where the commands should be inserted for (int i=0;iGetCommandsPtr(); + TShellMenuItemPtr spRootMenuItem = m_tShellExtMenuConfig.GetCommandRoot(); + m_tContextMenuHandler.Init(spRootMenuItem, hMenu, idCmdFirst, indexMenu, m_tShellExtData, m_tShellExtMenuConfig.GetShowShortcutIcons(), false); - // data about commands - int iCommandCount=0; + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, m_tContextMenuHandler.GetLastCommandID() - idCmdFirst + 1); +} - if(m_bShowPasteOption) - { - // paste - if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_PASTE_FLAG) - { - ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_STRING | (IsClipboardFormatAvailable(CF_HDROP) ? MF_ENABLED : MF_GRAYED), - idCmdFirst+0, pCommand[0].szCommand); - iCommandCount++; - } +STDMETHODIMP CMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) +{ + ATLTRACE(_T("CMenuExt::InvokeCommand()\n")); - if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_PASTESPECIAL_FLAG) - { - ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_STRING | (IsClipboardFormatAvailable(CF_HDROP) ? MF_ENABLED : MF_GRAYED), - idCmdFirst+1, pCommand[1].szCommand); - iCommandCount++; - } - } + // textual verbs are not supported by this extension + if(HIWORD(lpici->lpVerb) != 0) + return E_FAIL; - if (!m_bBackground) - { - CreateShortcutsMenu(idCmdFirst+5, g_pscsShared->bShowShortcutIcons); + // check options + HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + return E_FAIL; // required to process other InvokeCommand handlers. - // copy to > - if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_COPYTO_FLAG) - { - mii.cbSize=sizeof(MENUITEMINFO); - mii.fMask=MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; - mii.fType=MFT_STRING; - mii.fState=(g_pscsShared->iShortcutsCount > 0) ? MFS_ENABLED : MFS_GRAYED; - mii.wID=idCmdFirst+2; - mii.hSubMenu=m_mMenus.hShortcuts[0]; - mii.dwTypeData=pCommand[2].szCommand; - mii.cch=(UINT)_tcslen(pCommand[2].szCommand); + // find window + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(hWnd == NULL) + return E_FAIL; - ::InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); - // ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), - // (UINT)m_mMenus.hShortcuts[0], pCommand[2].szCommand); - iCommandCount++; - } + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpici->lpVerb)); + if(!spSelectedItem) + return E_FAIL; - // move to > - if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_MOVETO_FLAG) - { - mii.cbSize=sizeof(MENUITEMINFO); - mii.fMask=MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; - mii.fType=MFT_STRING; - mii.fState=(g_pscsShared->iShortcutsCount > 0) ? MFS_ENABLED : MFS_GRAYED; - mii.wID=idCmdFirst+3; - mii.hSubMenu=m_mMenus.hShortcuts[1]; - mii.dwTypeData=pCommand[3].szCommand; - mii.cch=(UINT)_tcslen(pCommand[3].szCommand); + // data retrieval and validation + if(!m_tShellExtData.VerifyItemCanBeExecuted(spSelectedItem)) + return E_FAIL; - ::InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); - // ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), - // (UINT)m_mMenus.hShortcuts[1], pCommand[3].szCommand); - iCommandCount++; - } + chcore::TPathContainer vSourcePaths; + chcore::TSmartPath spDestinationPath; + chcore::EOperationType eOperationType = chcore::eOperation_None; - // copy/move to special... > - if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG) - { - mii.cbSize=sizeof(MENUITEMINFO); - mii.fMask=MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; - mii.fType=MFT_STRING; - mii.fState=(g_pscsShared->iShortcutsCount > 0) ? MFS_ENABLED : MFS_GRAYED; - mii.wID=idCmdFirst+4; - mii.hSubMenu=m_mMenus.hShortcuts[2]; - mii.dwTypeData=pCommand[4].szCommand; - mii.cch=(UINT)_tcslen(pCommand[4].szCommand); + if(!m_tShellExtData.GetSourcePathsByItem(spSelectedItem, vSourcePaths)) + return E_FAIL; + if(!m_tShellExtData.GetDestinationPathByItem(spSelectedItem, spDestinationPath)) + return E_FAIL; + if(!m_tShellExtData.GetOperationTypeByItem(spSelectedItem, eOperationType)) + return E_FAIL; - ::InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); - // ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), - // (UINT)m_mMenus.hShortcuts[2], pCommand[4].szCommand); - iCommandCount++; - } - } + chcore::TTaskDefinition tTaskDefinition; + tTaskDefinition.SetSourcePaths(vSourcePaths); + tTaskDefinition.SetDestinationPath(spDestinationPath); + tTaskDefinition.SetOperationType(eOperationType); - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, g_pscsShared->iCommandCount+(m_bBackground ? 0 : 3*g_pscsShared->iShortcutsCount)); + // get task data as xml + chcore::TWStringData wstrData; + tTaskDefinition.StoreInString(wstrData); + + // fill struct + COPYDATASTRUCT cds; + cds.dwData = spSelectedItem->IsSpecialOperation() ? eCDType_TaskDefinitionContentSpecial : eCDType_TaskDefinitionContent; + cds.lpData = (void*)wstrData.GetData(); + cds.cbData = (DWORD)wstrData.GetBytesCount(); + + // send a message + ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + + return S_OK; } HRESULT CMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -418,43 +224,46 @@ break; case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT lpdis=(LPDRAWITEMSTRUCT) lParam; - DrawMenuItem(lpdis); - break; - } + return DrawMenuItem((LPDRAWITEMSTRUCT)lParam); case WM_MEASUREITEM: { - LPMEASUREITEMSTRUCT lpmis=(LPMEASUREITEMSTRUCT)lParam; + LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam; + if(!lpmis) + return E_FAIL; - // establish display text - int iShortcutIndex=(lpmis->itemID-m_uiFirstID-5)%g_pscsShared->iShortcutsCount; - _SHORTCUT* pShortcuts = g_pscsShared->GetShortcutsPtr(); + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpmis->itemID)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; - // measure the text - HWND hDesktop=GetDesktopWindow(); - HDC hDC=GetDC(hDesktop); - // get menu logfont NONCLIENTMETRICS ncm; - ncm.cbSize=sizeof(NONCLIENTMETRICS); + ncm.cbSize = sizeof(NONCLIENTMETRICS); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); - HFONT hFont=CreateFontIndirect(&ncm.lfMenuFont); - HFONT hOldFont=(HFONT)SelectObject(hDC, hFont); + HFONT hFont = CreateFontIndirect(&ncm.lfMenuFont); + if(!hFont) + return E_FAIL; + // measure the text + HWND hDesktop = GetDesktopWindow(); + HDC hDC = GetDC(hDesktop); + + HFONT hOldFont = (HFONT)SelectObject(hDC, hFont); + // calc text size SIZE size; - GetTextExtentPoint32(hDC, pShortcuts[iShortcutIndex].szName, (int)_tcslen(pShortcuts[iShortcutIndex].szName), &size); + GetTextExtentPoint32(hDC, spSelectedItem->GetName(), boost::numeric_cast(spSelectedItem->GetName().GetLength()), &size); // restore old settings SelectObject(hDC, hOldFont); ReleaseDC(hDesktop, hDC); + DeleteObject(hFont); // set - lpmis->itemWidth=size.cx+GetSystemMetrics(SM_CXMENUCHECK)+2*GetSystemMetrics(SM_CXSMICON); - lpmis->itemHeight = __max(size.cy+3, GetSystemMetrics(SM_CYMENU)+3); + lpmis->itemWidth = size.cx + GetSystemMetrics(SM_CXMENUCHECK) + 2 * GetSystemMetrics(SM_CXSMICON); + lpmis->itemHeight = __max(size.cy + 3, GetSystemMetrics(SM_CYMENU) + 3); break; } @@ -463,179 +272,133 @@ return S_OK; } -void CMenuExt::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) +HRESULT CMenuExt::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) { + if(!lpdis) + return E_FAIL; + // check if menu - if (lpdis->CtlType != ODT_MENU) - return; + if(lpdis->CtlType != ODT_MENU) + return S_OK; + // find command to be executed, if not found - fail + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(lpdis->itemID)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; + // margins and other stuff - const int iSmallIconWidth=GetSystemMetrics(SM_CXSMICON); - const int iSmallIconHeight=GetSystemMetrics(SM_CYSMICON); - const int iLeftMargin=GetSystemMetrics(SM_CXMENUCHECK)/2; - const int iRightMargin=GetSystemMetrics(SM_CXMENUCHECK)-iLeftMargin; + const int iSmallIconWidth = GetSystemMetrics(SM_CXSMICON); + const int iSmallIconHeight = GetSystemMetrics(SM_CYSMICON); + const int iLeftMargin = GetSystemMetrics(SM_CXMENUCHECK) / 2; + const int iRightMargin = GetSystemMetrics(SM_CXMENUCHECK) - iLeftMargin; - int iShortcutIndex=(lpdis->itemID-m_uiFirstID-5)%g_pscsShared->iShortcutsCount; - _SHORTCUT* pShortcuts=g_pscsShared->GetShortcutsPtr(); - // text color - HBRUSH hbr; - if (lpdis->itemState & ODS_SELECTED) + HBRUSH hBrush = NULL; + if(lpdis->itemState & ODS_SELECTED) { SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); - hbr=CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); } else { SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU)); - hbr=CreateSolidBrush(GetSysColor(COLOR_MENU)); + hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU)); } // draw background - RECT rcSelect=lpdis->rcItem; + RECT rcSelect = lpdis->rcItem; rcSelect.top++; rcSelect.bottom--; - FillRect(lpdis->hDC, &rcSelect, hbr); - DeleteObject(hbr); + FillRect(lpdis->hDC, &rcSelect, hBrush); + DeleteObject(hBrush); // get img list SHFILEINFO sfi; - HIMAGELIST himl=(HIMAGELIST)SHGetFileInfo(pShortcuts[iShortcutIndex].szPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON | SHGFI_SYSICONINDEX); - ImageList_Draw(himl, sfi.iIcon, lpdis->hDC, lpdis->rcItem.left+iLeftMargin, - lpdis->rcItem.top+(lpdis->rcItem.bottom-lpdis->rcItem.top+1-iSmallIconHeight)/2, ILD_TRANSPARENT); + HIMAGELIST hImageList = (HIMAGELIST)SHGetFileInfo(spSelectedItem->GetDestinationPathInfo().GetDefaultDestinationPath().ToString(), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON | SHGFI_SYSICONINDEX); + ImageList_Draw(hImageList, sfi.iIcon, lpdis->hDC, lpdis->rcItem.left + iLeftMargin, lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top + 1 - iSmallIconHeight) / 2, ILD_TRANSPARENT); RECT rcText; - rcText.left=iLeftMargin+iSmallIconWidth+iRightMargin; - rcText.top=lpdis->rcItem.top; - rcText.right=lpdis->rcItem.right; - rcText.bottom=lpdis->rcItem.bottom; + rcText.left = iLeftMargin + iSmallIconWidth + iRightMargin; + rcText.top = lpdis->rcItem.top; + rcText.right = lpdis->rcItem.right; + rcText.bottom = lpdis->rcItem.bottom; - DrawText(lpdis->hDC, pShortcuts[iShortcutIndex].szName, -1, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER); -} + DrawText(lpdis->hDC, spSelectedItem->GetName(), -1, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER); -void CMenuExt::CreateShortcutsMenu(UINT uiIDBase, bool bOwnerDrawn) -{ - // create empty menus - m_mMenus.hShortcuts[0]=CreatePopupMenu(); - m_mMenus.hShortcuts[1]=CreatePopupMenu(); - m_mMenus.hShortcuts[2]=CreatePopupMenu(); - - // fill with shortcuts - _SHORTCUT* pShortcuts=g_pscsShared->GetShortcutsPtr(); - TCHAR szText[256], szSize[32]; - ull_t ullFree; - - for (int i=0;iiShortcutsCount;i++) - { - // modify text - if (g_pscsShared->bShowFreeSpace && GetDynamicFreeSpace(pShortcuts[i].szPath, &ullFree, NULL)) - { - _sntprintf(szText, 256 - 1, _T("%s (%s)"), pShortcuts[i].szName, GetSizeString(ullFree, szSize, 32)); - szText[256 - 1] = _T('\0'); - _tcsncpy(pShortcuts[i].szName, szText, 127); - pShortcuts[i].szName[127]=_T('\0'); - } - - // add to all menus - for (int j=0;j<3;j++) - ::InsertMenu(m_mMenus.hShortcuts[j], i, MF_BYPOSITION | MF_ENABLED | (bOwnerDrawn ? MF_OWNERDRAW : 0), uiIDBase+i+j*g_pscsShared->iShortcutsCount, (bOwnerDrawn ? NULL : pShortcuts[i].szName)); - } + return S_OK; } STDMETHODIMP CMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) { + memset(pszName, 0, cchMax); + + if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) + return S_OK; + // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - { - pszName[0] = _T('\0'); - return hResult; - } - - LONG lFlags = eShellExt_None; - hResult = m_piShellExtControl->GetFlags(&lFlags); if(FAILED(hResult)) - { - pszName[0] = _T('\0'); return hResult; - } - if(!(lFlags & eShellExt_Enabled)) - { - pszName[0] = _T('\0'); + else if(hResult == S_FALSE) return S_OK; - } - if (uFlags == GCS_HELPTEXTW) + TShellMenuItemPtr spSelectedItem = m_tContextMenuHandler.GetCommandByMenuItemOffset(LOWORD(idCmd)); + if(!spSelectedItem || !spSelectedItem->SpecifiesDestinationPath()) + return E_FAIL; + + switch(uFlags) { - USES_CONVERSION; - // find window - HWND hWnd; - hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (!hWnd) - wcscpy(reinterpret_cast(pszName), L""); - - _COMMAND* pCommand=g_pscsShared->GetCommandsPtr(); - - switch (idCmd) + case GCS_HELPTEXTW: { - case 0: - case 1: - case 2: - case 3: - case 4: - { - CT2W ct2w(pCommand[idCmd].szDesc); - wcsncpy(reinterpret_cast(pszName), ct2w, cchMax); - break; - } - default: - _SHORTCUT* pShortcuts = g_pscsShared->GetShortcutsPtr(); - if ((int)(idCmd-5) < g_pscsShared->iShortcutsCount*3) - { - CT2W ct2w(pShortcuts[(idCmd-5)%g_pscsShared->iShortcutsCount].szPath); - wcsncpy(reinterpret_cast(pszName), ct2w, cchMax); - } - else - wcsncpy(reinterpret_cast(pszName), L"", cchMax); + wcsncpy(reinterpret_cast(pszName), spSelectedItem->GetItemTip(), spSelectedItem->GetItemTip().GetLength() + 1); + break; } - } - if (uFlags == GCS_HELPTEXTA) - { - // find window - HWND hWnd; - hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - - if (!hWnd) - strcpy(pszName, ""); - - _COMMAND* pCommand=g_pscsShared->GetCommandsPtr(); - - switch (idCmd) + case GCS_HELPTEXTA: { - case 0: - case 1: - case 2: - case 3: - case 4: - { - CT2A ct2a(pCommand[idCmd].szDesc); - strncpy(reinterpret_cast(pszName), ct2a, cchMax); - break; - } - default: // rest of commands - _SHORTCUT* pShortcuts = g_pscsShared->GetShortcutsPtr(); - if ((int)(idCmd-5) < g_pscsShared->iShortcutsCount*3) - { - CT2A ct2a(pShortcuts[(idCmd-5)%g_pscsShared->iShortcutsCount].szPath); - strncpy(pszName, ct2a, cchMax); - } - else - strncpy(pszName, "", cchMax); + USES_CONVERSION; + CT2A ct2a(spSelectedItem->GetItemTip()); + strncpy(reinterpret_cast(pszName), ct2a, strlen(ct2a) + 1); + break; } } return S_OK; } + +HRESULT CMenuExt::ReadShellConfig() +{ + try + { + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(hWnd == NULL) + return E_FAIL; + + // get cfg from ch + unsigned long ulSHMID = GetTickCount(); + ::SendMessage(hWnd, WM_GETCONFIG, eLocation_ContextMenu, ulSHMID); + + std::wstring strSHMName = IPCSupport::GenerateSHMName(ulSHMID); + + chcore::TSharedMemory tSharedMemory; + chcore::TWStringData wstrData; + chcore::TConfig cfgShellExtData; + + tSharedMemory.Open(strSHMName.c_str()); + tSharedMemory.Read(wstrData); + + //::MessageBox(NULL, wstrData.GetData(), _T("CMenuExt::ReadShellConfig"), MB_OK); + + cfgShellExtData.ReadFromString(wstrData); + + m_tShellExtMenuConfig.ReadFromConfig(cfgShellExtData, _T("ShellExtCfg")); + + return S_OK; + } + catch(...) + { + return E_FAIL; + } +} Index: src/chext/MenuExt.h =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/chext/MenuExt.h (.../MenuExt.h) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/chext/MenuExt.h (.../MenuExt.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -20,11 +20,11 @@ #define __MENUEXT_H_ #include "resource.h" // main symbols -#include "../libchcore/TTaskDefinition.h" +#include "TContextMenuHandler.h" +#include "..\common\TShellExtMenuConfig.h" +#include "TShellExtData.h" -/////// -// globals -void CutAmpersands(LPTSTR lpszString); +class TShellMenuItem; ///////////////////////////////////////////////////////////////////////////// // CMenuExt @@ -60,30 +60,16 @@ STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult); protected: - void DrawMenuItem(LPDRAWITEMSTRUCT lpdis); - void CreateShortcutsMenu(UINT uiIDBase, bool bOwnerDrawn); + HRESULT DrawMenuItem(LPDRAWITEMSTRUCT lpdis); -protected: - chcore::TPathContainer m_vPaths; + HRESULT ReadShellConfig(); - // for making sure DestroyMenu would be called - class CSubMenus - { - public: - CSubMenus() { hShortcuts[0]=NULL; hShortcuts[1]=NULL; hShortcuts[2]=NULL; }; - void Destroy() { for (int i=0;i<3;i++) { if (hShortcuts[i] != NULL) DestroyMenu(hShortcuts[i]); } }; - ~CSubMenus() { Destroy(); }; +private: + TShellExtData m_tShellExtData; - public: - HMENU hShortcuts[3]; - } m_mMenus; + TShellExtMenuConfig m_tShellExtMenuConfig; + TContextMenuHandler m_tContextMenuHandler; - bool m_bBackground; // folder or folder background - bool m_bShowPasteOption; // if the group of files have a files in it - - UINT m_uiFirstID; // first menu ID - bool m_bShown; // have the menu been already shown ? - IShellExtControl* m_piShellExtControl; }; Index: src/chext/StringHelpers.cpp =================================================================== diff -u -N --- src/chext/StringHelpers.cpp (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/chext/StringHelpers.cpp (revision 0) @@ -1,38 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2001-2008 by J�zef Starosczyk * -* ixen@copyhandler.com * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Library General Public License * -* (version 2) as published by the Free Software Foundation; * -* * -* 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 Library General Public * -* License along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include "stdafx.h" -#include "StringHelpers.h" -#include "stdio.h" - -LPTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize) -{ - if (dData < 0.0) - dData=0.0; - - if (dData < 1200.0) - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), dData, g_pscsShared->szSizes[0]); - else if (dData < 1228800.0) - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), static_cast(dData)/1024.0, g_pscsShared->szSizes[1]); - else if (dData < 1258291200.0) - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), static_cast(dData)/1048576.0, g_pscsShared->szSizes[2]); - else - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), static_cast(dData)/1073741824.0, g_pscsShared->szSizes[3]); - - return pszBuffer; -} Index: src/chext/StringHelpers.h =================================================================== diff -u -N --- src/chext/StringHelpers.h (revision cbbfad7da258eb9a7192461e61580202c684dfd0) +++ src/chext/StringHelpers.h (revision 0) @@ -1,56 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2001-2008 by J�zef Starosczyk * -* ixen@copyhandler.com * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Library General Public License * -* (version 2) as published by the Free Software Foundation; * -* * -* 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 Library General Public * -* License along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef __STRINGHELPERS_H__ -#define __STRINGHELPERS_H__ - -#include "..\common\ipcstructs.h" - -extern CSharedConfigStruct* g_pscsShared; - -LPTSTR GetSizeString(double dData, LPTSTR pszBuffer, size_t stMaxBufferSize); - -template -LPTSTR GetSizeString(T tData, LPTSTR pszBuffer, size_t stMaxBufferSize, bool bStrict = false) -{ - if (tData < 0) - tData=0; - - if (tData >= 1258291200 && (!bStrict || (tData % 1073741824) == 0)) - { - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), static_cast(tData)/1073741824.0, g_pscsShared->szSizes[3]); - return pszBuffer; - } - else if (tData >= 1228800 && (!bStrict || (tData % 1048576) == 0)) - { - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), static_cast(tData)/1048576.0, g_pscsShared->szSizes[2]); - return pszBuffer; - } - else if (tData >= 1200 && (!bStrict || (tData % 1024) == 0)) - { - _sntprintf(pszBuffer, stMaxBufferSize, _T("%.2f %s"), static_cast(tData)/1024.0, g_pscsShared->szSizes[1]); - return pszBuffer; - } - else - { - _sntprintf(pszBuffer, stMaxBufferSize, _T("%lu %s"), (unsigned long)tData, g_pscsShared->szSizes[0]); - return pszBuffer; - } -} - -#endif Index: src/chext/TContextMenuHandler.cpp =================================================================== diff -u -N --- src/chext/TContextMenuHandler.cpp (revision 0) +++ src/chext/TContextMenuHandler.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,123 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TContextMenuHandler.cpp +/// @date 2011/05/28 +/// @brief Contains implementation of class that handles menus. +// ============================================================================ +#include "stdafx.h" +#include "TContextMenuHandler.h" +#include +#include "../common/TShellExtMenuConfig.h" +#include + +TContextMenuHandler::TContextMenuHandler() : + m_uiNextMenuID(0), + m_bEnableOwnerDrawnPaths(false) +{ +} + +TContextMenuHandler::~TContextMenuHandler() +{ + Clear(); +} + +void TContextMenuHandler::Init(const TShellMenuItemPtr& spRootMenuItem, HMENU hMenu, UINT uiFirstItemID, UINT uiFirstItemPosition, const TShellExtData& rShellExtData, bool bEnableOwnerDrawnPaths, bool bOverrideDefaultItem) +{ + Clear(); + + m_uiFirstMenuID = uiFirstItemID; + m_uiNextMenuID = uiFirstItemID; + m_bEnableOwnerDrawnPaths = bEnableOwnerDrawnPaths; + + UpdateMenuRecursive(spRootMenuItem, hMenu, uiFirstItemPosition, rShellExtData, bOverrideDefaultItem); +} + +void TContextMenuHandler::UpdateMenuRecursive(const TShellMenuItemPtr& spRootMenuItem, HMENU hMenu, UINT uiFirstItemPosition, const TShellExtData& rShellExtData, bool bOverrideDefaultItem) +{ + for(size_t stIndex = 0; stIndex < spRootMenuItem->GetChildrenCount(); ++stIndex) + { + TShellMenuItemPtr spMenuItem = spRootMenuItem->GetChildAt(stIndex); + switch(spMenuItem->GetItemType()) + { + case TShellMenuItem::eGroupItem: + { + // special handling + HMENU hSubMenu = CreatePopupMenu(); + UpdateMenuRecursive(spMenuItem, hSubMenu, 0, rShellExtData, bOverrideDefaultItem); + + MENUITEMINFO mii; + mii.cch = _MAX_PATH; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.fState = (spRootMenuItem->GetChildrenCount() > 0) ? MFS_ENABLED : MFS_GRAYED; + mii.wID = m_uiNextMenuID++; + mii.hSubMenu = hSubMenu; + mii.dwTypeData = (PTSTR)(PCTSTR)spMenuItem->GetName(); + mii.cch = (UINT)spMenuItem->GetName().GetLength(); + + ::InsertMenuItem(hMenu, uiFirstItemPosition++, TRUE, &mii); + break; + } + case TShellMenuItem::eSeparatorItem: + { + ::InsertMenu(hMenu, uiFirstItemPosition++, MF_BYPOSITION | MF_SEPARATOR, m_uiNextMenuID++, NULL); + break; + } + case TShellMenuItem::eStandardItem: + { + bool bEnableOwnerDrawnItem = m_bEnableOwnerDrawnPaths && spMenuItem->SpecifiesDestinationPath(); + bool bEnableItem = rShellExtData.VerifyItemCanBeExecuted(spMenuItem); + + ::InsertMenu(hMenu, uiFirstItemPosition++, MF_BYPOSITION | MF_STRING | (bEnableItem ? MF_ENABLED : MF_GRAYED) | (bEnableOwnerDrawnItem ? MF_OWNERDRAW : 0), m_uiNextMenuID, spMenuItem->GetName()); + + if(bOverrideDefaultItem && rShellExtData.IsDefaultItem(spMenuItem)) + ::SetMenuDefaultItem(hMenu, m_uiNextMenuID, FALSE); + ++m_uiNextMenuID; + break; + } + default: + BOOST_ASSERT(false); // unhandled case + return; + } + m_mapMenuItems.insert(std::make_pair(m_uiNextMenuID - 1, spMenuItem)); // (-1, because it was already incremented to point to the next free ID) + } +} + +void TContextMenuHandler::Clear() +{ + m_mapMenuItems.clear(); + BOOST_FOREACH(HMENU hMenu, m_vHandlesToFree) + { + DestroyMenu(hMenu); + } + m_vHandlesToFree.clear(); + m_uiFirstMenuID = 0; + m_uiNextMenuID = 0; + m_bEnableOwnerDrawnPaths = false; +} + +TShellMenuItemPtr TContextMenuHandler::GetCommandByMenuItemOffset(UINT uiOffset) +{ + std::map::iterator iter = m_mapMenuItems.find(m_uiFirstMenuID + uiOffset); + if(iter != m_mapMenuItems.end()) + return (*iter).second; + else + return TShellMenuItemPtr(); +} Index: src/chext/TContextMenuHandler.h =================================================================== diff -u -N --- src/chext/TContextMenuHandler.h (revision 0) +++ src/chext/TContextMenuHandler.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,57 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TContextMenuHandler.h +/// @date 2011/05/28 +/// @brief Contains class which handles context menu. +// ============================================================================ +#ifndef __TCONTEXTMENUHANDLER_H__ +#define __TCONTEXTMENUHANDLER_H__ + +#include "TShellExtData.h" + +class TShellMenuItem; + +typedef boost::shared_ptr TShellMenuItemPtr; + +class TContextMenuHandler +{ +public: + TContextMenuHandler(); + ~TContextMenuHandler(); + + void Init(const TShellMenuItemPtr& spRootMenuItem, HMENU hMenu, UINT uiFirstItemID, UINT uiFirstItemPosition, const TShellExtData& rShellExtData, bool bEnableOwnerDrawnPaths, bool bOverrideDefaultItem); + void Clear(); + + UINT GetLastCommandID() const { return m_uiNextMenuID; } + TShellMenuItemPtr GetCommandByMenuItemOffset(UINT uiOffset); + +protected: + void UpdateMenuRecursive(const TShellMenuItemPtr& spRootMenuItem, HMENU hMenu, UINT uiFirstItemPosition, const TShellExtData& rShellExtData, bool bOverrideDefaultItem); + +private: + std::map m_mapMenuItems; + std::vector m_vHandlesToFree; + + UINT m_uiFirstMenuID; // menu ID from which the numbering started + UINT m_uiNextMenuID; // next menu ID to be used + + bool m_bEnableOwnerDrawnPaths; +}; + +#endif Index: src/chext/TShellExtData.cpp =================================================================== diff -u -N --- src/chext/TShellExtData.cpp (revision 0) +++ src/chext/TShellExtData.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,558 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TShellExtData.cpp +/// @date 2011/05/29 +/// @brief Implementation of class for handling data harvested with shell interfaces. +// ============================================================================ +#include "stdafx.h" +#include "TShellExtData.h" +#include "ShellPathsHelpers.h" +#include "../common/TShellExtMenuConfig.h" + +TShellExtData::TShellExtData() : + m_vPathsIDataObject(), + m_dwIDataObjectDropEffect(0), + m_pathPidlFolder(), + m_ulKeysState(eKey_None), + m_vPathsClipboard(), + m_dwClipboardDropEffect(0), + m_bFolderBackground(false), + m_eDefaultSystemMenuAction(eAction_None) +{ +} + +TShellExtData::~TShellExtData() +{ +} + +HRESULT TShellExtData::GatherDataFromInitialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject) +{ + Clear(); + + HRESULT hResult = S_OK; + + // read information from pidlFolder + if(pidlFolder) + hResult = ShellPathsHelpers::GetPathFromITEMIDLIST(pidlFolder, m_pathPidlFolder); + + // process IDataObject + if(SUCCEEDED(hResult) && piDataObject) + { + hResult = ShellPathsHelpers::GetPathsFromIDataObject(piDataObject, m_vPathsIDataObject); + if(hResult != S_OK) + hResult = E_FAIL; + if(SUCCEEDED(hResult)) + hResult = ReadPreferredDropEffectFromIDataObject(piDataObject); + } + + // Read clipboard paths with preferred drop effects + if(SUCCEEDED(hResult)) + hResult = ReadClipboard(); + + if(SUCCEEDED(hResult)) + { + ReadKeyboardState(); + + // experimentally deduced condition + m_bFolderBackground = (piDataObject == NULL) && (pidlFolder != NULL); + } + + return hResult; +} + +void TShellExtData::Clear() +{ + m_vPathsIDataObject.Clear(); + m_dwIDataObjectDropEffect = 0; + + m_pathPidlFolder.Clear(); + + m_ulKeysState = eKey_None; + + m_vPathsClipboard.Clear(); + m_dwClipboardDropEffect = 0; + + m_bFolderBackground = false; + + m_eDefaultSystemMenuAction = eAction_None; +} + +bool TShellExtData::CanServeAsSourcePaths(EDataSource eDataSource) const +{ + switch(eDataSource) + { + case eDS_Clipboard: + return !m_vPathsClipboard.IsEmpty(); + case eDS_IDataObject: + return !m_vPathsIDataObject.IsEmpty(); + case eDS_PidlFolder: + return !m_pathPidlFolder.IsEmpty(); + + default: + BOOST_ASSERT(false); + return false; + } +} + +bool TShellExtData::CanServeAsDestinationPath(EDataSource eDataSource) const +{ + switch(eDataSource) + { + case eDS_Clipboard: + return m_vPathsClipboard.GetCount() == 1 && (::GetFileAttributes(m_vPathsClipboard.GetAt(0).ToString()) & FILE_ATTRIBUTE_DIRECTORY); + case eDS_IDataObject: + return m_vPathsIDataObject.GetCount() == 1 && (::GetFileAttributes(m_vPathsIDataObject.GetAt(0).ToString()) & FILE_ATTRIBUTE_DIRECTORY); + case eDS_PidlFolder: + return !m_pathPidlFolder.IsEmpty() && (::GetFileAttributes(m_pathPidlFolder.ToString()) & FILE_ATTRIBUTE_DIRECTORY); + + default: + BOOST_ASSERT(false); + return false; + } +} + +bool TShellExtData::VerifyItemCanBeExecuted(const TShellMenuItemPtr& spMenuItem) const +{ + if(!spMenuItem || spMenuItem->IsGroupItem()) + return false; + + // where do we expect source paths to get from + switch(spMenuItem->GetSourcePathsInfo().GetSrcPathsSource()) + { + case TSourcePathsInfo::eSrcType_Clipboard: + { + if(!CanServeAsSourcePaths(eDS_Clipboard)) + return false; + break; + } + case TSourcePathsInfo::eSrcType_InitializePidlFolder: + { + if(!CanServeAsSourcePaths(eDS_PidlFolder)) + return false; + break; + } + case TSourcePathsInfo::eSrcType_InitializeIDataObject: + { + if(!CanServeAsSourcePaths(eDS_IDataObject)) + return false; + break; + } + case TSourcePathsInfo::eSrcType_InitializeAuto: + { + if(!CanServeAsSourcePaths(eDS_IDataObject) && !CanServeAsSourcePaths(eDS_PidlFolder)) + return false; + break; + } + default: + return false; + } + + // destination path + switch(spMenuItem->GetDestinationPathInfo().GetDstPathSource()) + { + case TDestinationPathInfo::eDstType_Clipboard: + { + if(!CanServeAsDestinationPath(eDS_Clipboard)) + return false; + break; + } + case TDestinationPathInfo::eDstType_InitializePidlFolder: + { + if(!CanServeAsDestinationPath(eDS_PidlFolder)) + return false; + break; + } + case TDestinationPathInfo::eDstType_InitializeIDataObject: + { + if(!CanServeAsDestinationPath(eDS_IDataObject)) + return false; + break; + } + case TDestinationPathInfo::eDstType_InitializeAuto: + { + if(!CanServeAsDestinationPath(eDS_IDataObject) && !CanServeAsDestinationPath(eDS_PidlFolder)) + return false; + break; + } + case TDestinationPathInfo::eDstType_Specified: + { + // here we don't check if this is a directory or if it exists - it's assumed that user knows what is he doing + if(!spMenuItem->GetDestinationPathInfo().GetDefaultDestinationPath().IsEmpty()) + return false; + break; + } + default: + return false; + } + + // if it passed all checks, means that we can allow this combination of source and destination path(s) to be used for command + return true; +} + +bool TShellExtData::IsDefaultItem(const TShellMenuItemPtr& spMenuItem) const +{ + if(!spMenuItem || spMenuItem->IsGroupItem() || spMenuItem->GetDefaultItemHint() == chcore::eOperation_None) + return false; + + // check if there was a state defined by reading the current context menu + if(m_eDefaultSystemMenuAction != eAction_None) + return m_eDefaultSystemMenuAction == spMenuItem->GetDefaultItemHint(); + + // check if there is preferred drop effect associated with the source path + switch(spMenuItem->GetSourcePathsInfo().GetSrcPathsSource()) + { + case TSourcePathsInfo::eSrcType_Clipboard: + { + if(m_dwClipboardDropEffect & DROPEFFECT_MOVE && spMenuItem->GetDefaultItemHint() == chcore::eOperation_Move || + m_dwClipboardDropEffect & DROPEFFECT_COPY && spMenuItem->GetDefaultItemHint() == chcore::eOperation_Copy) + return true; + break; + } + case TSourcePathsInfo::eSrcType_InitializePidlFolder: + break; // no associated info about drop effect + case TSourcePathsInfo::eSrcType_InitializeIDataObject: + { + if(m_dwIDataObjectDropEffect & DROPEFFECT_MOVE && spMenuItem->GetDefaultItemHint() == chcore::eOperation_Move || + m_dwIDataObjectDropEffect & DROPEFFECT_COPY && spMenuItem->GetDefaultItemHint() == chcore::eOperation_Copy) + return true; + break; + } + case TSourcePathsInfo::eSrcType_InitializeAuto: + { + if(m_dwIDataObjectDropEffect & DROPEFFECT_MOVE && spMenuItem->GetDefaultItemHint() == chcore::eOperation_Move || + m_dwIDataObjectDropEffect & DROPEFFECT_COPY && spMenuItem->GetDefaultItemHint() == chcore::eOperation_Copy) + return true; + break; + } + default: + return false; + } + + // step 3 - fallback - if there is no other info available, then assume copying, unless something else comes up from source/destination paths analysis + chcore::TSmartPath pathDestination; + if(!GetDestinationPathByItem(spMenuItem, pathDestination)) + return false; + + bool bIsSameDriveOrServerName = false; + switch(spMenuItem->GetSourcePathsInfo().GetSrcPathsSource()) + { + case TSourcePathsInfo::eSrcType_Clipboard: + { + if(!m_vPathsClipboard.IsEmpty()) + bIsSameDriveOrServerName = IsSameDrive(pathDestination, m_vPathsClipboard.GetAt(m_vPathsClipboard.GetCount() - 1)); + break; + } + case TSourcePathsInfo::eSrcType_InitializePidlFolder: + { + bIsSameDriveOrServerName = IsSameDrive(pathDestination, m_pathPidlFolder); + break; + } + case TSourcePathsInfo::eSrcType_InitializeIDataObject: + { + if(!m_vPathsIDataObject.IsEmpty()) + bIsSameDriveOrServerName = IsSameDrive(pathDestination, m_vPathsIDataObject.GetAt(m_vPathsIDataObject.GetCount() - 1)); + break; + } + case TSourcePathsInfo::eSrcType_InitializeAuto: + { + if(!m_vPathsIDataObject.IsEmpty()) + { + if(!m_vPathsIDataObject.IsEmpty()) + bIsSameDriveOrServerName = IsSameDrive(pathDestination, m_vPathsIDataObject.GetAt(m_vPathsIDataObject.GetCount() - 1)); + } + else if(!m_pathPidlFolder.IsEmpty()) + bIsSameDriveOrServerName = IsSameDrive(pathDestination, m_pathPidlFolder); + else + return false; + break; + } + } + + // depending on bIsSameDriveOrServerName we either are operating inside single disk volume or within single server, + // and since there is no other definition of operation to be performed, we assume either copy or move as default + if(bIsSameDriveOrServerName) + { + if(spMenuItem->GetDefaultItemHint() == chcore::eOperation_Move) + return true; + } + else + { + if(spMenuItem->GetDefaultItemHint() == chcore::eOperation_Copy) + return true; + } + return false; +} + +bool TShellExtData::GetSourcePathsByItem(const TShellMenuItemPtr& spMenuItem, chcore::TPathContainer& tSourcePaths) const +{ + if(!spMenuItem || spMenuItem->IsGroupItem()) + return false; + + tSourcePaths.Clear(); + + // where do we expect source paths to get from + switch(spMenuItem->GetSourcePathsInfo().GetSrcPathsSource()) + { + case TSourcePathsInfo::eSrcType_Clipboard: + tSourcePaths = m_vPathsClipboard; + break; + case TSourcePathsInfo::eSrcType_InitializePidlFolder: + tSourcePaths.Add(m_pathPidlFolder); + break; + case TSourcePathsInfo::eSrcType_InitializeIDataObject: + tSourcePaths = m_vPathsIDataObject; + break; + case TSourcePathsInfo::eSrcType_InitializeAuto: + { + if(!m_vPathsIDataObject.IsEmpty()) + tSourcePaths = m_vPathsIDataObject; + else if(!m_pathPidlFolder.IsEmpty()) + tSourcePaths.Add(m_pathPidlFolder); + else + return false; + break; + } + default: + return false; + } + + return true; +} + +bool TShellExtData::GetDestinationPathByItem(const TShellMenuItemPtr& spMenuItem, chcore::TSmartPath& tDestinationPath) const +{ + if(!spMenuItem || spMenuItem->IsGroupItem()) + return false; + + tDestinationPath.Clear(); + + // destination path + switch(spMenuItem->GetDestinationPathInfo().GetDstPathSource()) + { + case TDestinationPathInfo::eDstType_Clipboard: + { + if(m_vPathsClipboard.GetCount() != 1) + return false; + tDestinationPath = m_vPathsClipboard.GetAt(0); + break; + } + case TDestinationPathInfo::eDstType_InitializePidlFolder: + tDestinationPath = m_pathPidlFolder; + break; + case TDestinationPathInfo::eDstType_InitializeIDataObject: + { + if(m_vPathsIDataObject.GetCount() != 1) + return false; + tDestinationPath = m_vPathsIDataObject.GetAt(0); + break; + } + case TDestinationPathInfo::eDstType_InitializeAuto: + { + if(!m_vPathsIDataObject.IsEmpty()) + { + if(m_vPathsIDataObject.GetCount() != 1) + return false; + tDestinationPath = m_vPathsIDataObject.GetAt(0); + } + else if(!m_pathPidlFolder.IsEmpty()) + tDestinationPath = m_pathPidlFolder; + else + return false; + + break; + } + case TDestinationPathInfo::eDstType_Specified: + { + // here we don't check if this is a directory or if it exists - it's assumed that user knows what is he doing + if(!spMenuItem->GetDestinationPathInfo().GetDefaultDestinationPath().IsEmpty()) + return false; + tDestinationPath = spMenuItem->GetDestinationPathInfo().GetDefaultDestinationPath(); + break; + } + default: + return false; + } + + return true; +} + +bool TShellExtData::GetOperationTypeByItem(const TShellMenuItemPtr& spMenuItem, chcore::EOperationType& eOperationType) const +{ + if(!spMenuItem || spMenuItem->IsGroupItem()) + return false; + + eOperationType = chcore::eOperation_None; + + switch(spMenuItem->GetOperationTypeInfo().GetOperationTypeSource()) + { + case TOperationTypeInfo::eOpType_Autodetect: + { + // depending on the source and destination... + switch(spMenuItem->GetSourcePathsInfo().GetSrcPathsSource()) + { + case TSourcePathsInfo::eSrcType_Clipboard: + eOperationType = (m_dwClipboardDropEffect & DROPEFFECT_MOVE) ? chcore::eOperation_Move : chcore::eOperation_Copy; + break; + case TSourcePathsInfo::eSrcType_InitializeIDataObject: + case TSourcePathsInfo::eSrcType_InitializeAuto: + eOperationType = (m_dwIDataObjectDropEffect & DROPEFFECT_MOVE) ? chcore::eOperation_Move : chcore::eOperation_Copy; + break; + case TSourcePathsInfo::eSrcType_InitializePidlFolder: + return false; + break; + default: + return false; + } + break; + } + case TOperationTypeInfo::eOpType_Specified: + eOperationType = spMenuItem->GetOperationTypeInfo().GetDefaultOperationType(); + break; + default: + return false; + } + + return true; +} + +void TShellExtData::ReadKeyboardState() +{ + m_ulKeysState = ((GetKeyState(VK_SHIFT) & 0x80) ? eKey_Shift : 0) | + ((GetKeyState(VK_CONTROL) & 0x80) ? eKey_Ctrl : 0) | + ((GetKeyState(VK_MENU) & 0x80) ? eKey_Alt : 0); +} + +HRESULT TShellExtData::ReadPreferredDropEffectFromIDataObject(IDataObject* piDataObject) +{ + if(!piDataObject) + return E_INVALIDARG; + + // try to retrieve the preferred drop effect from the input data object + UINT uiPreferredDropEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); + if(!uiPreferredDropEffect) + return E_FAIL; + + FORMATETC fe = { (CLIPFORMAT)uiPreferredDropEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + + // if the drop effect does not exist - just report it + m_dwIDataObjectDropEffect = 0; + HRESULT hResult = piDataObject->QueryGetData(&fe); + if(hResult == S_OK) + { + STGMEDIUM medium; + hResult = piDataObject->GetData(&fe, &medium); + if(SUCCEEDED(hResult) && !medium.hGlobal) + hResult = E_FAIL; + if(SUCCEEDED(hResult)) + { + // specify operation + DWORD* pdwData = (DWORD*)GlobalLock(medium.hGlobal); + if(pdwData) + { + m_dwIDataObjectDropEffect = *pdwData; + GlobalUnlock(medium.hGlobal); + } + else + hResult = E_FAIL; + } + + ReleaseStgMedium(&medium); + } + + return hResult; +} + +HRESULT TShellExtData::ReadClipboard() +{ + HRESULT hResult = S_FALSE; + + if(IsClipboardFormatAvailable(CF_HDROP)) + { + // read paths from clipboard + if(!OpenClipboard(NULL)) + return E_FAIL; + + HANDLE hClipboardData = GetClipboardData(CF_HDROP); + if(!hClipboardData) + hResult = E_FAIL; + + if(SUCCEEDED(hResult)) + { + ShellPathsHelpers::GetPathsFromHDROP(static_cast(hClipboardData), m_vPathsClipboard); + + // check if there is also a hint about operation type + UINT nFormat = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); + if(IsClipboardFormatAvailable(nFormat)) + { + hClipboardData = GetClipboardData(nFormat); + if(!hClipboardData) + hResult = E_FAIL; + else + { + LPVOID pClipboardData = GlobalLock(hClipboardData); + if(!pClipboardData) + hResult = E_FAIL; + else + m_dwClipboardDropEffect = *((DWORD*)pClipboardData); + + GlobalUnlock(hClipboardData); + } + } + } + + CloseClipboard(); + + return hResult; + } + else + return S_FALSE; +} + +bool TShellExtData::IsSameDrive(const chcore::TSmartPath& spPath1, const chcore::TSmartPath& spPath2) const +{ + // NOTE: see operator== in TSmartPath for comments on path case sensitivity and possible issues with it + return (spPath1.HasDrive() && spPath2.HasDrive() && spPath1.GetDrive() == spPath2.GetDrive()) + || (spPath1.IsNetworkPath() && spPath2.IsNetworkPath() && spPath1.GetServerName() == spPath2.GetServerName()); +} + +void TShellExtData::ReadDefaultSelectionStateFromMenu(HMENU hMenu) +{ + // it's none by default + m_eDefaultSystemMenuAction = eAction_None; + + BOOST_ASSERT(hMenu != NULL); + if(hMenu) + { + MENUITEMINFO mii; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + + if(::GetMenuItemInfo(hMenu, 1, FALSE, &mii) && mii.fState & MFS_DEFAULT) + m_eDefaultSystemMenuAction = eAction_Copy; + if(::GetMenuItemInfo(hMenu, 2, FALSE, &mii) && mii.fState & MFS_DEFAULT) + m_eDefaultSystemMenuAction = eAction_Move; + if(::GetMenuItemInfo(hMenu, 3, FALSE, &mii) && mii.fState & MFS_DEFAULT) + m_eDefaultSystemMenuAction = eAction_Shortcut; + } +} + +TShellExtData::EActionSource TShellExtData::GetActionSource() const +{ + return (m_dwIDataObjectDropEffect != 0) ? (m_ulKeysState != eKey_None ? eSrc_Keyboard : eSrc_CtxMenu) : eSrc_DropMenu; +} \ No newline at end of file Index: src/chext/TShellExtData.h =================================================================== diff -u -N --- src/chext/TShellExtData.h (revision 0) +++ src/chext/TShellExtData.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,121 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TShellExtData.h +/// @date 2011/05/28 +/// @brief Contains class responsible for handling data harvested with shell interfaces. +// ============================================================================ +#ifndef __TSHELLEXTDATA_H__ +#define __TSHELLEXTDATA_H__ + +#include "..\libchcore\TPath.h" +#include "..\libchcore\EOperationTypes.h" + +class TShellMenuItem; + +typedef boost::shared_ptr TShellMenuItemPtr; + +class TShellExtData +{ +public: + enum EDataSource + { + eDS_IDataObject, + eDS_PidlFolder, + eDS_Clipboard, + }; + + enum EActionSource + { + eSrc_None = 0x0000, + eSrc_CtxMenu = 0x0100, + eSrc_DropMenu = 0x0200, + eSrc_Keyboard = 0x0400, + }; + +private: + /// State of the keyboard + enum EStateKeys + { + eKey_None = 0, + eKey_Ctrl = 1, + eKey_Alt = 2, + eKey_Shift = 4 + }; + + /// Default operation + enum EAction + { + eAction_None = 0x0000, + eAction_Copy = 0x0001, + eAction_Move = 0x0002, + eAction_Shortcut = 0x0004 + }; + +public: + TShellExtData(); + ~TShellExtData(); + + HRESULT GatherDataFromInitialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject); + void ReadDefaultSelectionStateFromMenu(HMENU hMenu); ///< Retrieves the state information from a menu handle; should be used only for drag&drop menu + + void Clear(); + + bool CanServeAsSourcePaths(EDataSource eDataSource) const; + bool CanServeAsDestinationPath(EDataSource eDataSource) const; + + bool VerifyItemCanBeExecuted(const TShellMenuItemPtr& spMenuItem) const; + bool IsDefaultItem(const TShellMenuItemPtr& spMenuItem) const; + + bool GetSourcePathsByItem(const TShellMenuItemPtr& spMenuItem, chcore::TPathContainer& tSourcePaths) const; + bool GetDestinationPathByItem(const TShellMenuItemPtr& spMenuItem, chcore::TSmartPath& tDestinationPath) const; + + bool GetOperationTypeByItem(const TShellMenuItemPtr& spMenuItem, chcore::EOperationType& eOperationType) const; + + EActionSource GetActionSource() const; + +protected: + void ReadKeyboardState(); ///< Reads current keyboard state + HRESULT ReadPreferredDropEffectFromIDataObject(IDataObject* piDataObject); + HRESULT ReadClipboard(); + + bool IsSameDrive(const chcore::TSmartPath& spPath1, const chcore::TSmartPath& spPath2) const; + +private: + // data gathered from IDataObject (Initialize()) + chcore::TPathContainer m_vPathsIDataObject; + DWORD m_dwIDataObjectDropEffect; + + // data gathered from ITEMIDLIST (Initialize) + chcore::TSmartPath m_pathPidlFolder; + + // Keys' state (Initialize()) + unsigned long m_ulKeysState; ///< State of the ctrl/shift/alt keys + + // data gathered from clipboard (Initialize()) + chcore::TPathContainer m_vPathsClipboard; + DWORD m_dwClipboardDropEffect; + + // clicked in folder background + bool m_bFolderBackground; + + // information retrieved from context menu + EAction m_eDefaultSystemMenuAction; +}; + +#endif // __TSHELLEXTDATA_H__ \ No newline at end of file Index: src/chext/chext.vc90.vcproj =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/chext/chext.vc90.vcproj (.../chext.vc90.vcproj) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/chext/chext.vc90.vcproj (.../chext.vc90.vcproj) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -395,45 +395,49 @@ Name="Tools" > + + +#include + +// helper method for concatenating strings +PCTSTR Concat(std::wstring& wstrBuffer, PCTSTR pszFirst, PCTSTR pszSecond) +{ + if(pszFirst && pszFirst[0] != _T('\0')) + { + wstrBuffer = pszFirst; + wstrBuffer += _T("."); + wstrBuffer += pszSecond; + } + else + wstrBuffer = pszSecond; + + return wstrBuffer.c_str(); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TOperationTypeInfo + +TOperationTypeInfo::TOperationTypeInfo() : + m_eOperationTypeSource(eOpType_Autodetect), + m_eDefaultOperationType(chcore::eOperation_None) +{ +} + +TOperationTypeInfo::TOperationTypeInfo(TOperationTypeInfo::EOperationTypeSource eType, chcore::EOperationType eDefaultOperationType) : + m_eOperationTypeSource(eType), + m_eDefaultOperationType(eDefaultOperationType) +{ +} + +void TOperationTypeInfo::SetOperationTypeInfo(TOperationTypeInfo::EOperationTypeSource eType, chcore::EOperationType eDefaultOperationType) +{ + m_eOperationTypeSource = eType; + m_eDefaultOperationType = eDefaultOperationType; +} + +TOperationTypeInfo::EOperationTypeSource TOperationTypeInfo::GetOperationTypeSource() const +{ + return m_eOperationTypeSource; +} + +chcore::EOperationType TOperationTypeInfo::GetDefaultOperationType() const +{ + return m_eDefaultOperationType; +} + +void TOperationTypeInfo::Clear() +{ + m_eOperationTypeSource = eOpType_Autodetect; + m_eDefaultOperationType = chcore::eOperation_None; +} + +void TOperationTypeInfo::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const +{ + std::wstring wstrBuffer; + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("OperationTypeSource")), m_eOperationTypeSource); + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DefaultOperationType")), m_eDefaultOperationType); +} + +bool TOperationTypeInfo::ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) +{ + std::wstring wstrBuffer; + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("OperationTypeSource")), *(int*)&m_eOperationTypeSource)) + return false; + return GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DefaultOperationType")), *(int*)&m_eDefaultOperationType); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TSourcePathsInfo + +TSourcePathsInfo::TSourcePathsInfo() : + m_eSrcPathsSource(eSrcType_InitializeAuto) +{ +} + +TSourcePathsInfo::TSourcePathsInfo(TSourcePathsInfo::ESrcPathsSource eSrcPathSource) : + m_eSrcPathsSource(eSrcPathSource) +{ +} + +void TSourcePathsInfo::SetSourcePathsInfo(TSourcePathsInfo::ESrcPathsSource eSrcPathSource) +{ + m_eSrcPathsSource = eSrcPathSource; +} + +TSourcePathsInfo::ESrcPathsSource TSourcePathsInfo::GetSrcPathsSource() const +{ + return m_eSrcPathsSource; +} + +void TSourcePathsInfo::Clear() +{ + m_eSrcPathsSource = eSrcType_InitializeAuto; +} + +void TSourcePathsInfo::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const +{ + std::wstring wstrBuffer; + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("SrcPathsSource")), m_eSrcPathsSource); +} + +bool TSourcePathsInfo::ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) +{ + std::wstring wstrBuffer; + return GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("SrcPathsSource")), *(int*)&m_eSrcPathsSource); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TDestinationPathInfo +// + +TDestinationPathInfo::TDestinationPathInfo() : + m_eDstPathSource(eDstType_InitializeAuto), + m_pathDestination() +{ +} + +TDestinationPathInfo::TDestinationPathInfo(TDestinationPathInfo::EDstPathsSource eDstPathSource, const chcore::TSmartPath& pathDestination) : + m_eDstPathSource(eDstPathSource), + m_pathDestination(pathDestination) +{ +} + +void TDestinationPathInfo::SetDestinationPathInfo(EDstPathsSource eDstPathSource, const chcore::TSmartPath& pathDestination) +{ + m_eDstPathSource = eDstPathSource; + m_pathDestination = pathDestination; +} + +TDestinationPathInfo::EDstPathsSource TDestinationPathInfo::GetDstPathSource() const +{ + return m_eDstPathSource; +} + +chcore::TSmartPath TDestinationPathInfo::GetDefaultDestinationPath() const +{ + return m_pathDestination; +} + +void TDestinationPathInfo::Clear() +{ + m_eDstPathSource = eDstType_InitializeAuto; + m_pathDestination.Clear(); +} + +void TDestinationPathInfo::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const +{ + std::wstring wstrBuffer; + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DstPathSource")), m_eDstPathSource); + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DefaultDestinationPath")), m_pathDestination); +} + +bool TDestinationPathInfo::ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) +{ + std::wstring wstrBuffer; + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DstPathSource")), *(int*)&m_eDstPathSource)) + return false; + return GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DefaultDestinationPath")), m_pathDestination); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TShellMenuItem + +TShellMenuItem::TShellMenuItem() : + m_tOperationType(), + m_tSourcePaths(), + m_tDestinationPath(), + m_eItemType(eSeparatorItem), + m_bSpecialOperation(false), + m_eDefaultItemHint(chcore::eOperation_None) +{ +} + +TShellMenuItem::TShellMenuItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip, const TOperationTypeInfo& rOperationType, const TSourcePathsInfo& rSourcePaths, const TDestinationPathInfo& rDestinationPath, bool bSpecialOperation, chcore::EOperationType eDefaultItemHint) : + m_strName(wstrName), + m_strItemTip(wstrItemTip), + m_tOperationType(rOperationType), + m_tSourcePaths(rSourcePaths), + m_tDestinationPath(rDestinationPath), + m_eItemType(eStandardItem), + m_bSpecialOperation(bSpecialOperation), + m_eDefaultItemHint(eDefaultItemHint) +{ +} + +TShellMenuItem::TShellMenuItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip) : + m_strName(wstrName), + m_strItemTip(wstrItemTip), + m_tOperationType(), + m_tSourcePaths(), + m_tDestinationPath(), + m_eItemType(eGroupItem), + m_bSpecialOperation(false), + m_eDefaultItemHint(chcore::eOperation_None) +{ +} + +TShellMenuItem::~TShellMenuItem() +{ +} + +void TShellMenuItem::Clear() +{ + m_eItemType = eSeparatorItem; + + m_strName.Clear(); + m_strItemTip.Clear(); + + m_tOperationType.Clear(); + m_tSourcePaths.Clear(); + m_tDestinationPath.Clear(); + + m_bSpecialOperation = false; + m_eDefaultItemHint = chcore::eOperation_None; + + m_vChildItems.clear(); +} + +void TShellMenuItem::InitSeparatorItem() +{ + Clear(); + + m_eItemType = eSeparatorItem; +} + +void TShellMenuItem::InitStandardItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip, const TOperationTypeInfo& rOperationType, const TSourcePathsInfo& rSourcePaths, const TDestinationPathInfo& rDestinationPath, bool bSpecialOperation, chcore::EOperationType eDefaultItemHint) +{ + Clear(); + + m_eItemType = eStandardItem; + + m_strName = wstrName; + m_strItemTip = wstrItemTip; + m_tOperationType = rOperationType; + m_tSourcePaths = rSourcePaths; + m_tDestinationPath = rDestinationPath; + + m_bSpecialOperation = bSpecialOperation; + m_eDefaultItemHint = eDefaultItemHint; +} + +void TShellMenuItem::InitGroupItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip) +{ + Clear(); + + m_eItemType = eGroupItem; + m_strName = wstrName; + m_strItemTip = wstrItemTip; +} + +size_t TShellMenuItem::GetChildrenCount() const +{ + return m_vChildItems.size(); +} + +TShellMenuItemPtr TShellMenuItem::GetChildAt(size_t stIndex) const +{ + return m_vChildItems[stIndex]; +} + +void TShellMenuItem::AddChild(const TShellMenuItemPtr& rItem) +{ + m_vChildItems.push_back(rItem); +} + +void TShellMenuItem::SetChildAt(size_t stIndex, const TShellMenuItemPtr& rItem) +{ + m_vChildItems[stIndex] = rItem; +} + +void TShellMenuItem::InsertChildAt(size_t stIndex, const TShellMenuItemPtr& rItem) +{ + m_vChildItems.insert(m_vChildItems.begin() + stIndex, rItem); +} + +void TShellMenuItem::RemoveChildAt(size_t stIndex) +{ + m_vChildItems.erase(m_vChildItems.begin() + stIndex); +} + +void TShellMenuItem::RemoveAllChildren() +{ + m_vChildItems.clear(); +} + +void TShellMenuItem::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const +{ + std::wstring wstrBuffer; + + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemType")), m_eItemType); + switch(m_eItemType) + { + case eSeparatorItem: + break; + case eGroupItem: + { + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemName")), m_strName); + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemDescription")), m_strItemTip); + + BOOST_FOREACH(const TShellMenuItemPtr& rItem, m_vChildItems) + { + chcore::TConfig cfgItem; + rItem->StoreInConfig(cfgItem, _T("")); + rConfig.AddSubConfig(Concat(wstrBuffer, pszNodeName, _T("Subitems.Subitem")), cfgItem); + } + + break; + } + case eStandardItem: + { + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemName")), m_strName); + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemDescription")), m_strItemTip); + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("SpecialOperation")), m_bSpecialOperation); + SetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DefaultItemHint")), m_eDefaultItemHint); + + m_tOperationType.StoreInConfig(rConfig, Concat(wstrBuffer, pszNodeName, _T("OperationType"))); + m_tSourcePaths.StoreInConfig(rConfig, Concat(wstrBuffer, pszNodeName, _T("SourcePaths"))); + m_tDestinationPath.StoreInConfig(rConfig, Concat(wstrBuffer, pszNodeName, _T("DestinationPath"))); + + break; + } + default: + BOOST_ASSERT(false); // unhandled case + } +} + +bool TShellMenuItem::ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) +{ + Clear(); + + std::wstring wstrBuffer; + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemType")), *(int*)&m_eItemType)) + return false; + switch(m_eItemType) + { + case eSeparatorItem: + break; + case eGroupItem: + { + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemName")), m_strName)) + return false; + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemDescription")), m_strItemTip)) + return false; + + chcore::TConfigArray vCfgs; + if(rConfig.ExtractMultiSubConfigs(Concat(wstrBuffer, pszNodeName, _T("Subitems.Subitem")), vCfgs)) + { + for(size_t stIndex = 0; stIndex < vCfgs.GetCount(); ++stIndex) + { + chcore::TConfig& rCfg = vCfgs.GetAt(stIndex); + + TShellMenuItemPtr spItem(boost::make_shared()); + spItem->ReadFromConfig(rCfg, NULL); + m_vChildItems.push_back(spItem); + } + } + + break; + } + case eStandardItem: + { + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemName")), m_strName)) + return false; + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("ItemDescription")), m_strItemTip)) + return false; + + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("SpecialOperation")), m_bSpecialOperation)) + return false; + if(!GetConfigValue(rConfig, Concat(wstrBuffer, pszNodeName, _T("DefaultItemHint")), *(int*)&m_eDefaultItemHint)) + return false; + + if(!m_tOperationType.ReadFromConfig(rConfig, Concat(wstrBuffer, pszNodeName, _T("OperationType")))) + return false; + + if(!m_tSourcePaths.ReadFromConfig(rConfig, Concat(wstrBuffer, pszNodeName, _T("SourcePaths")))) + return false; + + if(!m_tDestinationPath.ReadFromConfig(rConfig, Concat(wstrBuffer, pszNodeName, _T("DestinationPath")))) + return false; + + break; + } + default: + BOOST_ASSERT(false); // unhandled case + return false; + } + + return true; +} + +TShellExtMenuConfig::TShellExtMenuConfig() : + m_bInterceptDragAndDrop(false), + m_bInterceptKeyboardActions(false), + m_bInterceptCtxMenuActions(false), + m_bShowShortcutIcons(false), + m_spCommandsRoot(boost::make_shared(_T(""), _T(""))) +{ +} + +TShellExtMenuConfig::~TShellExtMenuConfig() +{ +} + +void TShellExtMenuConfig::Clear() +{ + m_spCommandsRoot->Clear(); + + m_bInterceptDragAndDrop = false; + m_bInterceptKeyboardActions = false; + m_bInterceptCtxMenuActions = false; + m_bShowShortcutIcons = false; +} + +// commands support +TShellMenuItemPtr TShellExtMenuConfig::GetCommandRoot() +{ + return m_spCommandsRoot; +} + +void TShellExtMenuConfig::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const +{ + std::wstring strBuffer; + SetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("InterceptDragAndDrop")), m_bInterceptDragAndDrop); + SetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("InterceptKeyboardActions")), m_bInterceptKeyboardActions); + SetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("InterceptCtxMenuActions")), m_bInterceptCtxMenuActions); + SetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("ShowShortcutIcons")), m_bShowShortcutIcons); + + m_spCommandsRoot->StoreInConfig(rConfig, Concat(strBuffer, pszNodeName, _T("RootItem"))); +} + +bool TShellExtMenuConfig::ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) +{ + Clear(); + + std::wstring strBuffer; + if(!GetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("InterceptDragAndDrop")), m_bInterceptDragAndDrop)) + return false; + if(!GetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("InterceptKeyboardActions")), m_bInterceptKeyboardActions)) + return false; + if(!GetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("InterceptCtxMenuActions")), m_bInterceptCtxMenuActions)) + return false; + if(!GetConfigValue(rConfig, Concat(strBuffer, pszNodeName, _T("ShowShortcutIcons")), m_bShowShortcutIcons)) + return false; + + if(!m_spCommandsRoot->ReadFromConfig(rConfig, Concat(strBuffer, pszNodeName, _T("RootItem")))) + return false; + + return true; +} Index: src/common/TShellExtMenuConfig.h =================================================================== diff -u -N --- src/common/TShellExtMenuConfig.h (revision 0) +++ src/common/TShellExtMenuConfig.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,254 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TShellExtMenuConfig.h +/// @date 2011/05/06 +/// @brief Contains class responsible for maintaining shell ext configuration (via shared mem). +// ============================================================================ +#ifndef __TSHELLEXTMENUCONFIG_H__ +#define __TSHELLEXTMENUCONFIG_H__ + +#include "../libchcore/EOperationTypes.h" +#include "../libchcore/TPath.h" + +namespace chcore { class TConfig; } + +class TShellMenuItem; + +typedef boost::shared_ptr TShellMenuItemPtr; + +// specifies information about operation type +class TOperationTypeInfo +{ +public: + enum EOperationTypeSource + { + eOpType_Specified, + eOpType_Autodetect, + }; + +public: + TOperationTypeInfo(); + TOperationTypeInfo(EOperationTypeSource eType, chcore::EOperationType eDefaultOperationType); + + void SetOperationTypeInfo(EOperationTypeSource eType, chcore::EOperationType eDefaultOperationType); + + EOperationTypeSource GetOperationTypeSource() const; + chcore::EOperationType GetDefaultOperationType() const; + + void Clear(); + + void StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const; + bool ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName); + +private: + EOperationTypeSource m_eOperationTypeSource; + chcore::EOperationType m_eDefaultOperationType; // default operation type +}; + +// specifies information about source paths +class TSourcePathsInfo +{ +public: + enum ESrcPathsSource + { + eSrcType_Clipboard, + eSrcType_InitializePidlFolder, + eSrcType_InitializeIDataObject, + eSrcType_InitializeAuto, + }; + +public: + TSourcePathsInfo(); + TSourcePathsInfo(ESrcPathsSource eSrcPathSource); + + void SetSourcePathsInfo(ESrcPathsSource eSrcPathSource); + ESrcPathsSource GetSrcPathsSource() const; + + void Clear(); + + void StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const; + bool ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName); + +private: + ESrcPathsSource m_eSrcPathsSource; +}; + +// specifies information about destination path +class TDestinationPathInfo +{ +public: + enum EDstPathsSource + { + eDstType_Specified, + eDstType_Clipboard, + eDstType_InitializePidlFolder, + eDstType_InitializeIDataObject, + eDstType_InitializeAuto, + }; + +public: + TDestinationPathInfo(); + TDestinationPathInfo(EDstPathsSource eDstPathSource, const chcore::TSmartPath& pathDestination); + + void SetDestinationPathInfo(EDstPathsSource eDstPathSource, const chcore::TSmartPath& m_pathDestination); + EDstPathsSource GetDstPathSource() const; + chcore::TSmartPath GetDefaultDestinationPath() const; + + void Clear(); + + void StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const; + bool ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName); + +private: + EDstPathsSource m_eDstPathSource; + chcore::TSmartPath m_pathDestination; +}; + +// class is not to be exported from DLL (because we're using wstrings here!) +class TShellMenuItem +{ +public: + enum EItemType + { + eStandardItem, + eGroupItem, + eSeparatorItem + }; + +public: + TShellMenuItem(); + TShellMenuItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip, const TOperationTypeInfo& rOperationType, const TSourcePathsInfo& rSourcePaths, const TDestinationPathInfo& rDestinationPath, + bool bSpecialOperation, chcore::EOperationType eDefaultItemHint = chcore::eOperation_None); + TShellMenuItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip); + + ~TShellMenuItem(); + + // initializer for separator item + void InitSeparatorItem(); + + // initializer for standard item + void InitStandardItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip, const TOperationTypeInfo& rOperationType, const TSourcePathsInfo& rSourcePaths, const TDestinationPathInfo& rDestinationPath, + bool bSpecialOperation, chcore::EOperationType eDefaultItemHint = chcore::eOperation_None); + + // initializer for group item + void InitGroupItem(const chcore::TString& wstrName, const chcore::TString& wstrItemTip); + + // clears everything + void Clear(); + + // retrieving attributes - common ones + chcore::TString GetName() const { return m_strName; } + chcore::TString GetItemTip() const { return m_strItemTip; } + + // retrieving attributes - standard items only + const TOperationTypeInfo& GetOperationTypeInfo() const { return m_tOperationType; } + const TDestinationPathInfo& GetDestinationPathInfo() const { return m_tDestinationPath; } + const TSourcePathsInfo& GetSourcePathsInfo() const { return m_tSourcePaths; } + + chcore::EOperationType GetDefaultItemHint() const { return m_eDefaultItemHint; } + + bool IsGroupItem() const { return m_eItemType == eGroupItem; } + bool IsSeparator() const { return m_eItemType == eSeparatorItem; } + bool IsStandardItem() const { return m_eItemType == eStandardItem; } + EItemType GetItemType() const { return m_eItemType; } + + bool IsSpecialOperation() const { return m_bSpecialOperation; } + + // helper - retrieves info if the destination path is already specified + bool SpecifiesDestinationPath() const { return !IsGroupItem() && !m_tDestinationPath.GetDstPathSource() == TDestinationPathInfo::eDstType_Specified; } + // helper - retrieves info if this command requires some paths present in clipboard to be enabled + bool RequiresClipboardPaths() const { return !IsGroupItem() && (m_tDestinationPath.GetDstPathSource() == TDestinationPathInfo::eDstType_Clipboard || m_tSourcePaths.GetSrcPathsSource() == TSourcePathsInfo::eSrcType_Clipboard); } + + // operations on children + size_t GetChildrenCount() const; + TShellMenuItemPtr GetChildAt(size_t stIndex) const; + + void AddChild(const TShellMenuItemPtr& rItem); + void SetChildAt(size_t stIndex, const TShellMenuItemPtr& rItem); + void InsertChildAt(size_t stIndex, const TShellMenuItemPtr& rItem); + + void RemoveChildAt(size_t stIndex); + void RemoveAllChildren(); + + // serialization + void StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const; + bool ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName); + +private: + EItemType m_eItemType; + + chcore::TString m_strName; + chcore::TString m_strItemTip; + + // where to get the operation type from? (specified here / autodetect (with fallback specified here)) + TOperationTypeInfo m_tOperationType; + + // where to get the destination path? (specified here / read from clipboard / retrieved in IShellExtInit::Initialize()) + TDestinationPathInfo m_tDestinationPath; + + // where to get source paths? (read from clipboard / retrieved in IShellExtInit::Initialize()) + TSourcePathsInfo m_tSourcePaths; + + // states if the operation allows for modifications before execution (special operation) + bool m_bSpecialOperation; + + // hints that this item is to be made default (bold), when detected operation type is equal to this operation type + chcore::EOperationType m_eDefaultItemHint; + + std::vector m_vChildItems; +}; + +class TShellExtMenuConfig +{ +public: + TShellExtMenuConfig(); + ~TShellExtMenuConfig(); + + void Clear(); + + // commands support + TShellMenuItemPtr GetCommandRoot(); + + // options + void SetInterceptDragAndDrop(bool bEnable) { m_bInterceptDragAndDrop = bEnable; } + bool GetInterceptDragAndDrop() const { return m_bInterceptDragAndDrop; } + + void SetInterceptKeyboardActions(bool bEnable) { m_bInterceptKeyboardActions = bEnable; } + bool GetInterceptKeyboardActions() const { return m_bInterceptKeyboardActions; } + + void SetInterceptCtxMenuActions(bool bEnable) { m_bInterceptCtxMenuActions = bEnable; } + bool GetInterceptCtxMenuActions() const { return m_bInterceptCtxMenuActions; } + + void SetShowShortcutIcons(bool bEnable) { m_bShowShortcutIcons = bEnable; } + bool GetShowShortcutIcons() const { return m_bShowShortcutIcons; } + + // serialize/unserialize + void StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName) const; + bool ReadFromConfig(chcore::TConfig& rConfig, PCTSTR pszNodeName); + +private: + TShellMenuItemPtr m_spCommandsRoot; // root under which there are commands placed + + bool m_bInterceptDragAndDrop; + bool m_bInterceptKeyboardActions; + bool m_bInterceptCtxMenuActions; + bool m_bShowShortcutIcons; // show shell icons with shortcuts ? +}; + +#endif Index: src/common/ipcstructs.h =================================================================== diff -u -N -r3d1951f52696fe21e01618e1bbfb9e14745a3827 -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/common/ipcstructs.h (.../ipcstructs.h) (revision 3d1951f52696fe21e01618e1bbfb9e14745a3827) +++ src/common/ipcstructs.h (.../ipcstructs.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -19,82 +19,32 @@ #ifndef __SHAREDDATA_H__ #define __SHAREDDATA_H__ -#include "../libchcore/TTaskDefinition.h" +#include // messages used #define WM_GETCONFIG WM_USER+20 -// config type to get from program -#define GC_DRAGDROP 0x00 -#define GC_EXPLORER 0x01 - -// command properties (used in menu displaying) -#pragma pack(push, 1) -struct _COMMAND -{ - UINT uiCommandID; // command ID - would be send - chcore::EOperationType eOperationType; - TCHAR szCommand[128]; // command name - TCHAR szDesc[128]; // and it's description -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct _SHORTCUT -{ - TCHAR szName[128]; - TCHAR szPath[_MAX_PATH]; -}; -#pragma pack(pop) - enum ECopyDataType { eCDType_TaskDefinitionContent, eCDType_TaskDefinitionContentSpecial, eCDType_CommandLineArguments, }; -// shared memory size in bytes -#define SHARED_BUFFERSIZE 65536 +enum ELocation +{ + eLocation_DragAndDropMenu, + eLocation_ContextMenu +}; -// structure used for passing data from program to DLL -// the rest is a dynamic texts -class CSharedConfigStruct +namespace IPCSupport { -public: - enum EFlags + static std::wstring GenerateSHMName(unsigned long ulRequestID) { - // drag&drop flags - OPERATION_MASK = 0x00ffffff, - DD_COPY_FLAG = 0x00000001, - DD_MOVE_FLAG = 0x00000002, - DD_COPYMOVESPECIAL_FLAG = 0x00000004, + std::wstring wstrName = _T("CHExtSHM_"); + wstrName += boost::lexical_cast(ulRequestID); + return wstrName; + } +} - EC_PASTE_FLAG = 0x00000010, - EC_PASTESPECIAL_FLAG = 0x00000020, - EC_COPYTO_FLAG = 0x00000040, - EC_MOVETO_FLAG = 0x00000080, - EC_COPYMOVETOSPECIAL_FLAG = 0x00000100, - - eFlag_InterceptDragAndDrop = 0x00000200, - eFlag_InterceptKeyboardActions = 0x00000400, - eFlag_InterceptCtxMenuActions = 0x00000800 - }; -public: - _SHORTCUT* GetShortcutsPtr() const { return (_SHORTCUT*)(byData + iCommandCount * sizeof(_COMMAND)); } - _COMMAND* GetCommandsPtr() const { return (_COMMAND*)byData; } - -public: - UINT uiFlags; // what items and how to display in drag&drop ctx menu & explorer.ctx.menu - - bool bShowFreeSpace; // show the free space by the shortcuts ? - TCHAR szSizes[6][64]; // names of the kB, GB, ... - bool bShowShortcutIcons; // show shell icons with shortcuts ? - - int iCommandCount; // count of commands stored at the beginning of a buffer - int iShortcutsCount; // count of shortcuts to display in submenus - - BYTE byData[SHARED_BUFFERSIZE]; // buffer for texts and other stuff -}; - #endif Index: src/libchcore/EOperationTypes.h =================================================================== diff -u -N --- src/libchcore/EOperationTypes.h (revision 0) +++ src/libchcore/EOperationTypes.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,43 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file EOperationTypes.h +/// @date 2011/05/26 +/// @brief Defines an enumeration type with supported operations. +// ============================================================================ +#ifndef __EOPERATIONTYPES_H__ +#define __EOPERATIONTYPES_H__ + +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +// enum represents type of the operation handled by the task +enum EOperationType +{ + eOperation_None, + eOperation_Copy, + eOperation_Move, + + // add new operation types before this enum value + eOperation_Max +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/ErrorCodes.h =================================================================== diff -u -N -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/libchcore/ErrorCodes.h (.../ErrorCodes.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -31,6 +31,16 @@ eUnhandledCase = 3, eMissingData = 4, eUnsupportedVersion = 5, + + // shared memory + eCannotOpenSharedMemory = 6, + eSharedMemoryNotOpen = 7, + eSharedMemoryInvalidFormat = 8, + eSharedMemoryAlreadyExists = 9, + + // threads + eMutexTimedOut = 10, + }; END_CHCORE_NAMESPACE Index: src/libchcore/TConfig.cpp =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TConfig.cpp (.../TConfig.cpp) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/TConfig.cpp (.../TConfig.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -32,23 +32,24 @@ #pragma warning(disable: 4702 4512) #include #pragma warning(pop) +#include BEGIN_CHCORE_NAMESPACE /////////////////////////////////////////////////////////////////////////////////////////////// // class TConfigNotifier -TConfigNotifier::TConfigNotifier(void (*pfnCallback)(const std::set&, void*), void* pParam) : -m_pfnCallback(pfnCallback), -m_pParam(pParam) +TConfigNotifier::TConfigNotifier(void (*pfnCallback)(const TStringSet&, void*), void* pParam) : + m_pfnCallback(pfnCallback), + m_pParam(pParam) { } TConfigNotifier::~TConfigNotifier() { } -void TConfigNotifier::operator()(const std::set& rsetPropNames) +void TConfigNotifier::operator()(const TStringSet& rsetPropNames) { if(!m_pfnCallback) THROW(_T("Invalid pointer"), 0, 0, 0); @@ -107,17 +108,78 @@ } ///////////////////////////////////////////////////////////////////////////////////////////// +// class TConfigArray + +TConfigArray::TConfigArray() +{ +} + +TConfigArray::TConfigArray(const TConfigArray& rSrc) : + m_vConfigs(rSrc.m_vConfigs) +{ +} + +TConfigArray::~TConfigArray() +{ +} + +TConfigArray& TConfigArray::operator=(const TConfigArray& rSrc) +{ + if(this != &rSrc) + { + m_vConfigs = rSrc.m_vConfigs; + } + + return *this; +} + +size_t TConfigArray::GetCount() const +{ + return m_vConfigs.size(); +} + +bool TConfigArray::IsEmpty() const +{ + return m_vConfigs.empty(); +} + +const TConfig& TConfigArray::GetAt(size_t stIndex) const +{ + return m_vConfigs[stIndex]; +} + +TConfig& TConfigArray::GetAt(size_t stIndex) +{ + return m_vConfigs[stIndex]; +} + +void TConfigArray::Add(const TConfig& rSrc) +{ + m_vConfigs.push_back(rSrc); +} + +void TConfigArray::RemoveAt(size_t stIndex) +{ + m_vConfigs.erase(m_vConfigs.begin() + stIndex); +} + +void TConfigArray::Clear() +{ + m_vConfigs.clear(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// // class TConfig TConfig::TConfig() : -m_bDelayedEnabled(false), -m_bModified(false) + m_bDelayedEnabled(false), + m_bModified(false) { } TConfig::TConfig(const TConfig& rSrc) : -m_bDelayedEnabled(false), -m_bModified(rSrc.m_bModified) + m_bDelayedEnabled(false), + m_bModified(rSrc.m_bModified) { boost::shared_lock lock(rSrc.m_lock); @@ -136,7 +198,7 @@ m_bModified = rSrc.m_bModified; m_strFilePath = rSrc.m_strFilePath; m_bDelayedEnabled = false; - m_setDelayedNotifications.clear(); + m_setDelayedNotifications.Clear(); } return *this; @@ -159,7 +221,7 @@ ClearNL(); // also clears m_bModified m_strFilePath = pszFile; - std::wifstream ifs(m_strFilePath.c_str(), std::ios_base::in); + std::wifstream ifs(m_strFilePath, std::ios_base::in); try { boost::property_tree::xml_parser::read_xml(ifs, m_propTree); @@ -176,7 +238,7 @@ boost::shared_lock lock(m_lock); if(!bOnlyIfModified || m_bModified) { - std::wofstream ofs(m_strFilePath.c_str(), std::ios_base::out); + std::wofstream ofs(m_strFilePath, std::ios_base::out); boost::property_tree::xml_parser::write_xml(ofs, m_propTree); m_bModified = false; @@ -254,9 +316,9 @@ { m_propTree.clear(); m_bModified = false; - m_setDelayedNotifications.clear(); + m_setDelayedNotifications.Clear(); m_bDelayedEnabled = false; - m_strFilePath.clear(); + m_strFilePath.Clear(); } // value setting/retrieval @@ -378,14 +440,14 @@ return *this; } -std::wstring TConfig::GetString(PCTSTR pszPropName, const std::wstring& strDefault) const +TString TConfig::GetString(PCTSTR pszPropName, const TString& strDefault) const { boost::shared_lock lock(m_lock); std::wstring wstrData = m_propTree.get(pszPropName, std::wstring(strDefault)); return wstrData.c_str(); } -bool TConfig::GetValue(PCTSTR pszPropName, std::wstring& rstrValue) const +bool TConfig::GetValue(PCTSTR pszPropName, TString& rstrValue) const { std::wstring wstrData; bool bResult = InternalGetValue(m_propTree, pszPropName, wstrData, m_lock); @@ -394,7 +456,7 @@ return bResult; } -TConfig& TConfig::SetValue(PCTSTR pszPropName, const std::wstring& strValue) +TConfig& TConfig::SetValue(PCTSTR pszPropName, const TString& strValue) { std::wstring wstrData = strValue; if(InternalSetValue(m_propTree, m_bModified, m_lock, pszPropName, wstrData)) @@ -403,17 +465,26 @@ return *this; } -bool TConfig::GetValue(PCTSTR pszPropName, std::vector& rvValues) const +bool TConfig::GetValue(PCTSTR pszPropName, TStringArray& rvValues) const { boost::shared_lock lock(m_lock); - rvValues.clear(); + rvValues.Clear(); - boost::optional children = m_propTree.get_child_optional(pszPropName); + // get rid of the last part of the property to get to the parent holding the real entries + std::wstring wstrPropertyName = pszPropName; + boost::iterator_range iterFnd = boost::find_last(wstrPropertyName, _T(".")); + if(iterFnd.begin() == wstrPropertyName.end()) + return false; + + std::wstring wstrNewPropName; + wstrNewPropName.insert(wstrNewPropName.end(), wstrPropertyName.begin(), iterFnd.begin()); + + boost::optional children = m_propTree.get_child_optional(wstrNewPropName); if(children.is_initialized()) { BOOST_FOREACH(const boost::property_tree::wiptree::value_type& rEntry, children.get()) { - rvValues.push_back(rEntry.second.data().c_str()); + rvValues.Add(rEntry.second.data().c_str()); } return true; @@ -422,15 +493,15 @@ return false; } -void TConfig::SetValue(PCTSTR pszPropName, const std::vector& rvValues) +void TConfig::SetValue(PCTSTR pszPropName, const TStringArray& rvValues) { // separate scope for mutex (to avoid calling notifier inside critical section) { boost::unique_lock lock(m_lock); m_propTree.erase(pszPropName); - BOOST_FOREACH(const std::wstring& strValue, rvValues) + for(size_t stIndex = 0; stIndex < rvValues.GetCount(); ++stIndex) { - m_propTree.add(pszPropName, strValue); + m_propTree.add(pszPropName, (const wchar_t*)rvValues.GetAt(stIndex)); } m_bModified = true; @@ -457,19 +528,28 @@ return false; } -bool TConfig::ExtractMultiSubConfigs(PCTSTR pszSubTreeName, std::vector& rSubConfigs) const +bool TConfig::ExtractMultiSubConfigs(PCTSTR pszSubTreeName, TConfigArray& rSubConfigs) const { - TConfig cfg; - boost::shared_lock lock(m_lock); - boost::optional optChildren = m_propTree.get_child_optional(pszSubTreeName); + std::wstring wstrPropertyName = pszSubTreeName; + boost::iterator_range iterFnd = boost::find_last(wstrPropertyName, _T(".")); + if(iterFnd.begin() == wstrPropertyName.end()) + return false; + + std::wstring wstrNewPropName; + wstrNewPropName.insert(wstrNewPropName.end(), wstrPropertyName.begin(), iterFnd.begin()); + + boost::optional optChildren = m_propTree.get_child_optional(wstrNewPropName); if(optChildren.is_initialized()) { BOOST_FOREACH(const boost::property_tree::wiptree::value_type& rEntry, optChildren.get()) { + std::wstring strData = rEntry.first.c_str(); + + TConfig cfg; cfg.m_propTree = rEntry.second; - rSubConfigs.push_back(cfg); + rSubConfigs.Add(cfg); } return true; @@ -504,12 +584,12 @@ m_propTree.erase(pszNodeName); } -void TConfig::ConnectToNotifier(void (*pfnCallback)(const std::set&, void*), void* pParam) +void TConfig::ConnectToNotifier(void (*pfnCallback)(const TStringSet&, void*), void* pParam) { m_notifier.connect(TConfigNotifier(pfnCallback, pParam)); } -void TConfig::DisconnectFromNotifier(void (*pfnCallback)(const std::set&, void*)) +void TConfig::DisconnectFromNotifier(void (*pfnCallback)(const TStringSet&, void*)) { m_notifier.disconnect(TConfigNotifier(pfnCallback, NULL)); } @@ -522,30 +602,30 @@ void TConfig::ResumeNotifications() { - std::set setNotifications; + TStringSet setNotifications; // separate scope for shared mutex (to avoid calling notifier inside critical section) { boost::upgrade_lock lock(m_lock); if(m_bDelayedEnabled) { m_bDelayedEnabled = false; - if(!m_setDelayedNotifications.empty()) + if(!m_setDelayedNotifications.IsEmpty()) { setNotifications = m_setDelayedNotifications; boost::upgrade_to_unique_lock upgraded_lock(lock); - m_setDelayedNotifications.clear(); + m_setDelayedNotifications.Clear(); } } } // NOTE: no locking here! - if(!setNotifications.empty()) + if(!setNotifications.IsEmpty()) SendNotification(setNotifications); } -void TConfig::SendNotification(const std::set& rsetInfo) +void TConfig::SendNotification(const TStringSet& rsetInfo) { // separate scope for shared mutex (to avoid calling notifier inside critical section) { @@ -554,7 +634,7 @@ { boost::upgrade_to_unique_lock upgraded_lock(lock); - m_setDelayedNotifications.insert(rsetInfo.begin(), rsetInfo.end()); + m_setDelayedNotifications.Insert(rsetInfo); return; } } @@ -572,14 +652,14 @@ { boost::upgrade_to_unique_lock upgraded_lock(lock); - m_setDelayedNotifications.insert(pszInfo); + m_setDelayedNotifications.Insert(pszInfo); return; } } // NOTE: we don't lock here - std::set setData; - setData.insert(pszInfo); + TStringSet setData; + setData.Insert(pszInfo); m_notifier(setData); } Index: src/libchcore/TConfig.h =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TConfig.h (.../TConfig.h) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/TConfig.h (.../TConfig.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -28,6 +28,8 @@ #include #include #pragma warning(pop) +#include "TStringSet.h" +#include "TStringArray.h" BEGIN_CHCORE_NAMESPACE @@ -37,20 +39,49 @@ class TConfigNotifier { public: - TConfigNotifier(void (*pfnCallback)(const std::set&, void*), void* pParam); + TConfigNotifier(void (*pfnCallback)(const TStringSet&, void*), void* pParam); ~TConfigNotifier(); - void operator()(const std::set& rsetPropNames); + void operator()(const TStringSet& rsetPropNames); TConfigNotifier& operator=(const TConfigNotifier& rNotifier); bool operator==(const TConfigNotifier& rNotifier) const; private: - void (*m_pfnCallback)(const std::set&, void*); + void (*m_pfnCallback)(const TStringSet&, void*); void* m_pParam; }; +class TConfig; + +class LIBCHCORE_API TConfigArray +{ +public: + TConfigArray(); + TConfigArray(const TConfigArray& rSrc); + ~TConfigArray(); + + TConfigArray& operator=(const TConfigArray& rSrc); + + size_t GetCount() const; + bool IsEmpty() const; + + const TConfig& GetAt(size_t stIndex) const; + TConfig& GetAt(size_t stIndex); + + void Add(const TConfig& rSrc); + + void RemoveAt(size_t stIndex); + void Clear(); + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::vector m_vConfigs; +#pragma warning(pop) +}; + // class for handling configuration settings class LIBCHCORE_API TConfig { @@ -102,30 +133,30 @@ bool GetValue(PCTSTR pszPropName, double& dValue) const; TConfig& SetValue(PCTSTR pszPropName, double dValue); - std::wstring GetString(PCTSTR pszPropName, const std::wstring& strDefault) const; - bool GetValue(PCTSTR pszPropName, std::wstring& rstrValue) const; - TConfig& SetValue(PCTSTR pszPropName, const std::wstring& strValue); + TString GetString(PCTSTR pszPropName, const TString& strDefault) const; + bool GetValue(PCTSTR pszPropName, TString& rstrValue) const; + TConfig& SetValue(PCTSTR pszPropName, const TString& strValue); - bool GetValue(PCTSTR pszPropName, std::vector& rvValues) const; - void SetValue(PCTSTR pszPropName, const std::vector& rvValues); + bool GetValue(PCTSTR pszPropName, TStringArray& rvValues) const; + void SetValue(PCTSTR pszPropName, const TStringArray& rvValues); void DeleteNode(PCTSTR pszNodeName); // extraction of subtrees bool ExtractSubConfig(PCTSTR pszSubTreeName, TConfig& rSubConfig) const; - bool ExtractMultiSubConfigs(PCTSTR pszSubTreeName, std::vector& rSubConfigs) const; + bool ExtractMultiSubConfigs(PCTSTR pszSubTreeName, TConfigArray& rSubConfigs) const; void PutSubConfig(PCTSTR pszSubTreeName, const TConfig& rSubConfig); void AddSubConfig(PCTSTR pszSubTreeName, const TConfig& rSubConfig); // property change notification - void ConnectToNotifier(void (*pfnCallback)(const std::set&, void*), void* pParam); - void DisconnectFromNotifier(void (*pfnCallback)(const std::set&, void*)); + void ConnectToNotifier(void (*pfnCallback)(const TStringSet&, void*), void* pParam); + void DisconnectFromNotifier(void (*pfnCallback)(const TStringSet&, void*)); void DelayNotifications(); void ResumeNotifications(); protected: - void SendNotification(const std::set& rsetInfo); + void SendNotification(const TStringSet& rsetInfo); void SendNotification(PCTSTR pszInfo); void ClearNL(); @@ -134,10 +165,10 @@ #pragma warning(push) #pragma warning(disable: 4251) boost::property_tree::wiptree m_propTree; - std::wstring m_strFilePath; + TString m_strFilePath; - boost::signals2::signal&)> m_notifier; - std::set m_setDelayedNotifications; + boost::signals2::signal m_notifier; + TStringSet m_setDelayedNotifications; bool m_bDelayedEnabled; bool m_bModified; ///< Modification state - cleared when saving Index: src/libchcore/TConfigSerializers.h =================================================================== diff -u -N -r116ff594271c0042255be4bfe8ac7bdd13530d6b -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TConfigSerializers.h (.../TConfigSerializers.h) (revision 116ff594271c0042255be4bfe8ac7bdd13530d6b) +++ src/libchcore/TConfigSerializers.h (.../TConfigSerializers.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -33,15 +33,15 @@ static void StoreInConfig(const CString& strValue, chcore::TConfig& rConfig, PCTSTR pszPropName) { - rConfig.SetValue(pszPropName, std::wstring((PCTSTR)strValue)); + rConfig.SetValue(pszPropName, TString((PCTSTR)strValue)); } static bool ReadFromConfig(CString& strValue, const chcore::TConfig& rConfig, PCTSTR pszPropName) { - std::wstring wstrData; + TString wstrData; bool bRes = rConfig.GetValue(pszPropName, wstrData); if(bRes) - strValue = wstrData.c_str(); + strValue = wstrData; else strValue.Empty(); return bRes; @@ -52,10 +52,10 @@ static void StoreInConfig(const std::vector& vValues, chcore::TConfig& rConfig, PCTSTR pszPropName) { // convert to vector of wstrings (ineffective; there should be a better way to do this) - std::vector vToStore; + TStringArray vToStore; BOOST_FOREACH(const CString& strVal, vValues) { - vToStore.push_back((PCTSTR)strVal); + vToStore.Add((PCTSTR)strVal); } rConfig.SetValue(pszPropName, vToStore); @@ -65,14 +65,14 @@ { vValues.clear(); - std::vector vToConvert; + TStringArray vToConvert; bool bRes = rConfig.GetValue(pszPropName, vToConvert); if(bRes) { - BOOST_FOREACH(const std::wstring& strValue, vToConvert) + for(size_t stIndex = 0; stIndex < vToConvert.GetCount(); ++stIndex) { - vValues.push_back(strValue.c_str()); + vValues.push_back((PCTSTR)vToConvert.GetAt(stIndex)); } } Index: src/libchcore/TPath.cpp =================================================================== diff -u -N -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TPath.cpp (.../TPath.cpp) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) +++ src/libchcore/TPath.cpp (.../TPath.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -205,7 +205,15 @@ else if(m_pPath == NULL || rPath.m_pPath == NULL) return false; else + { + // NOTE: Windows paths are usually case insensitive and that would warrant usage of + // iequals, however, in very specific cases (i.e. enabling case sensitivity for ntfs, + // network paths) we need case sensitivity. + // For now we'll try to support case sensitivity. If that will ever be a problem + // we'll need to support case insensitivity (not trivial though). +// return boost::iequals(m_pPath->m_strPath, rPath.m_pPath->m_strPath); return m_pPath->m_strPath == rPath.m_pPath->m_strPath; + } } // ============================================================================ @@ -254,10 +262,10 @@ // ============================================================================ TSmartPath TSmartPath::operator+(const TSmartPath& rPath) const { - if(rPath.m_pPath && rPath.m_pPath->m_strPath.length() > 0) + if(rPath.m_pPath && rPath.m_pPath->m_strPath.GetLength() > 0) { // if this path is empty, then return the input one - if(!m_pPath || rPath.m_pPath->m_strPath.length() == 0) + if(!m_pPath || rPath.m_pPath->m_strPath.GetLength() == 0) return rPath; else { @@ -276,7 +284,7 @@ spNewPath.m_pPath->m_strPath += rPath.m_pPath->m_strPath; else { - spNewPath.m_pPath->m_strPath.erase(m_pPath->m_strPath.length() - 1); + spNewPath.m_pPath->m_strPath.DeleteChar(m_pPath->m_strPath.GetLength() - 1); spNewPath.m_pPath->m_strPath += rPath.m_pPath->m_strPath; } @@ -301,10 +309,10 @@ TSmartPath& TSmartPath::operator+=(const TSmartPath& rPath) { // if there is no path inside rPath, then there is no point in doing anything - if(rPath.m_pPath && rPath.m_pPath->m_strPath.length() > 0) + if(rPath.m_pPath && rPath.m_pPath->m_strPath.GetLength() > 0) { // if this path is empty, then optimize by just assigning the input path to this one - if(!m_pPath || m_pPath->m_strPath.length() == 0) + if(!m_pPath || m_pPath->m_strPath.GetLength() == 0) *this = rPath; else { @@ -321,7 +329,7 @@ m_pPath->m_strPath += rPath.m_pPath->m_strPath; else { - m_pPath->m_strPath.erase(m_pPath->m_strPath.length() - 1); + m_pPath->m_strPath.DeleteChar(m_pPath->m_strPath.GetLength() - 1); m_pPath->m_strPath += rPath.m_pPath->m_strPath; } } @@ -353,7 +361,7 @@ /// @brief Initializes this path object with path contained in string. /// @param[in] strPath - string containing path. // ============================================================================ -void TSmartPath::FromString(const std::wstring& strPath) +void TSmartPath::FromString(const TString& strPath) { PrepareToWrite(); m_pPath->m_strPath = strPath; @@ -369,7 +377,7 @@ const wchar_t* TSmartPath::ToString() const { if(m_pPath) - return m_pPath->m_strPath.c_str(); + return m_pPath->m_strPath; return _T(""); } @@ -380,9 +388,9 @@ /// @brief Retrieves the string containing path. /// @return String containing path. // ============================================================================ -std::wstring TSmartPath::ToWString() const +TString TSmartPath::ToWString() const { - std::wstring wstrPath; + TString wstrPath; if(m_pPath) wstrPath = m_pPath->m_strPath; return wstrPath; @@ -405,9 +413,9 @@ else { if(bCaseSensitive) - return boost::equals(m_pPath->m_strPath, rPath.m_pPath->m_strPath); + return m_pPath->m_strPath.Compare(rPath.m_pPath->m_strPath) == 0; else - return boost::iequals(m_pPath->m_strPath, rPath.m_pPath->m_strPath); + return m_pPath->m_strPath.CompareNoCase(rPath.m_pPath->m_strPath) == 0; } } @@ -439,13 +447,14 @@ } else { - std::vector vStrings; - boost::split(vStrings, m_pPath->m_strPath, boost::is_any_of(_T("\\/"))); + TStringArray vStrings; + m_pPath->m_strPath.Split(_T("\\/"), vStrings); - BOOST_FOREACH(const std::wstring& pathComponent, vStrings) + for(size_t stIndex = 0; stIndex < vStrings.GetCount(); ++stIndex) { - if(!pathComponent.empty()) - vComponents.push_back(PathFromWString(pathComponent)); + const TString& strComponent = vStrings.GetAt(stIndex); + if(!strComponent.IsEmpty()) + vComponents.push_back(PathFromWString(strComponent)); } } } @@ -464,9 +473,9 @@ return false; if(bCaseSensitive) - return boost::starts_with(m_pPath->m_strPath, rPath.m_pPath->m_strPath); + return m_pPath->m_strPath.StartsWith(rPath.m_pPath->m_strPath); else - return boost::istarts_with(m_pPath->m_strPath, rPath.m_pPath->m_strPath); + return m_pPath->m_strPath.StartsWithNoCase(rPath.m_pPath->m_strPath); } // ============================================================================ @@ -485,14 +494,14 @@ bool bStartsWith = false; if(bCaseSensitive) - bStartsWith = boost::starts_with(m_pPath->m_strPath, rReferenceBasePath.m_pPath->m_strPath); + bStartsWith = m_pPath->m_strPath.StartsWith(rReferenceBasePath.m_pPath->m_strPath); else - bStartsWith = boost::istarts_with(m_pPath->m_strPath, rReferenceBasePath.m_pPath->m_strPath); + bStartsWith = m_pPath->m_strPath.StartsWithNoCase(rReferenceBasePath.m_pPath->m_strPath); if(bStartsWith) { PrepareToWrite(); - m_pPath->m_strPath.erase(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + rReferenceBasePath.m_pPath->m_strPath.length()); + m_pPath->m_strPath.Delete(0, rReferenceBasePath.m_pPath->m_strPath.GetLength()); } else THROW(_T("Incompatible paths"), 0, 0, 0); @@ -513,9 +522,9 @@ bool bEndsWith = false; if(bCaseSensitive) - bEndsWith = m_pPath && boost::ends_with(m_pPath->m_strPath, pszPostfix); + bEndsWith = m_pPath && m_pPath->m_strPath.EndsWith(pszPostfix); else - bEndsWith = m_pPath && boost::iends_with(m_pPath->m_strPath, pszPostfix); + bEndsWith = m_pPath && m_pPath->m_strPath.EndsWithNoCase(pszPostfix); if(!bEndsWith) { @@ -539,14 +548,14 @@ bool bEndsWith = false; if(bCaseSensitive) - bEndsWith = m_pPath && boost::ends_with(m_pPath->m_strPath, pszPostfix); + bEndsWith = m_pPath && m_pPath->m_strPath.EndsWith(pszPostfix); else - bEndsWith = m_pPath && boost::iends_with(m_pPath->m_strPath, pszPostfix); + bEndsWith = m_pPath && m_pPath->m_strPath.EndsWithNoCase(pszPostfix); if(bEndsWith) { PrepareToWrite(); - m_pPath->m_strPath.erase(m_pPath->m_strPath.end() - _tcslen(pszPostfix), m_pPath->m_strPath.end()); + m_pPath->m_strPath.Delete(m_pPath->m_strPath.GetLength() - _tcslen(pszPostfix), m_pPath->m_strPath.GetLength() - _tcslen(pszPostfix)); } } @@ -562,7 +571,7 @@ if(!m_pPath) return false; - return (m_pPath->m_strPath.length() > 2 && IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1))); // "\\server_name" + return (m_pPath->m_strPath.GetLength() > 2 && IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1))); // "\\server_name" } // ============================================================================ @@ -577,7 +586,7 @@ if(!m_pPath) return false; - return (m_pPath->m_strPath.length() == 2 && m_pPath->m_strPath.at(1) == _T(':')); + return (m_pPath->m_strPath.GetLength() == 2 && m_pPath->m_strPath.GetAt(1) == _T(':')); } // ============================================================================ @@ -592,7 +601,7 @@ if(!m_pPath) return false; - return (m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')); + return (m_pPath->m_strPath.GetLength() >= 2 && m_pPath->m_strPath.GetAt(1) == _T(':')); } // ============================================================================ @@ -607,12 +616,12 @@ if(!m_pPath) return TSmartPath(); - if(m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')) + if(m_pPath->m_strPath.GetLength() >= 2 && m_pPath->m_strPath.GetAt(1) == _T(':')) { - if(m_pPath->m_strPath.length() == 2) + if(m_pPath->m_strPath.GetLength() == 2) return *this; else - return PathFromWString(std::wstring(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + 2)); // c: for c:\windows\test.cpp + return PathFromWString(m_pPath->m_strPath.Left(2)); // c: for c:\windows\test.cpp } return TSmartPath(); @@ -630,10 +639,10 @@ if(!m_pPath) return false; - return (m_pPath->m_strPath.length() > 2 && // must have at least 3 characters... - IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1)) && // ... the first two of which are separators... - std::isalnum(m_pPath->m_strPath.at(2)) && // ... followed by at least one alphanumeric character... - m_pPath->m_strPath.find_first_of(_T("\\/"), 3) == std::wstring::npos); // ... with no additional separators (so \\abc is true, \\abc\ is not). + return (m_pPath->m_strPath.GetLength() > 2 && // must have at least 3 characters... + IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1)) && // ... the first two of which are separators... + std::isalnum(m_pPath->m_strPath.GetAt(2)) && // ... followed by at least one alphanumeric character... + m_pPath->m_strPath.FindFirstOf(_T("\\/"), 3) == TString::npos); // ... with no additional separators (so \\abc is true, \\abc\ is not). } // ============================================================================ @@ -648,7 +657,7 @@ if(!m_pPath) return false; - return (m_pPath->m_strPath.length() > 2 && IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1)) && std::isalnum(m_pPath->m_strPath.at(2))); + return (m_pPath->m_strPath.GetLength() > 2 && IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1)) && std::isalnum(m_pPath->m_strPath.GetAt(2))); } // ============================================================================ @@ -663,14 +672,14 @@ if(!m_pPath) return TSmartPath(); - std::wstring wstrPath; - if(m_pPath->m_strPath.length() > 2 && IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1)) && std::isalnum(m_pPath->m_strPath.at(2))) + TString wstrPath; + if(m_pPath->m_strPath.GetLength() > 2 && IsSeparator(m_pPath->m_strPath.GetAt(0)) && IsSeparator(m_pPath->m_strPath.GetAt(1)) && std::isalnum(m_pPath->m_strPath.GetAt(2))) { - size_t stEndPos = m_pPath->m_strPath.find_first_of(_T("\\/"), 2); - if(stEndPos == std::wstring::npos) - wstrPath.insert(wstrPath.end(), m_pPath->m_strPath.begin(), m_pPath->m_strPath.end()); + size_t stEndPos = m_pPath->m_strPath.FindFirstOf(_T("\\/"), 2); + if(stEndPos == TString::npos) + wstrPath = m_pPath->m_strPath; else - wstrPath.insert(wstrPath.end(), m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + stEndPos); + wstrPath = m_pPath->m_strPath.Left(stEndPos - 1); return PathFromWString(wstrPath); } @@ -689,8 +698,8 @@ if(!m_pPath) return false; - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - return (stIndex != std::wstring::npos); + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + return (stIndex != TString::npos); } // ============================================================================ @@ -705,12 +714,9 @@ if(!m_pPath) return TSmartPath(); - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - if(stIndex != std::wstring::npos) - { - std::wstring wstrPath(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + stIndex + 1); - return PathFromWString(wstrPath); - } + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + if(stIndex != TString::npos) + return PathFromWString(m_pPath->m_strPath.Left(stIndex)); return TSmartPath(); } @@ -729,12 +735,12 @@ size_t stStart = 0; if(IsNetworkPath()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); + stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"), 2); else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); + stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.find_last_of(_T("/\\")); - return (stStart != std::wstring::npos && stEnd >= stStart); + size_t stEnd = m_pPath->m_strPath.FindLastOf(_T("/\\")); + return (stStart != TString::npos && stEnd >= stStart); } // ============================================================================ @@ -751,16 +757,13 @@ size_t stStart = 0; if(IsNetworkPath()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); + stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"), 2); else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); + stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.find_last_of(_T("/\\")); - if(stStart != std::wstring::npos && stEnd >= stStart) - { - std::wstring wstrDir(m_pPath->m_strPath.begin() + stStart, m_pPath->m_strPath.begin() + stEnd + 1); - return PathFromWString(wstrDir); - } + size_t stEnd = m_pPath->m_strPath.FindLastOf(_T("/\\")); + if(stStart != TString::npos && stEnd >= stStart) + return PathFromWString(m_pPath->m_strPath.MidByPos(stStart, stEnd + 1)); return TSmartPath(); } @@ -777,14 +780,14 @@ if(!m_pPath) return false; - size_t stStart = m_pPath->m_strPath.find_last_of(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.find_last_of(_T(".")); - if((stStart == std::wstring::npos && stEnd == std::wstring::npos)) + size_t stStart = m_pPath->m_strPath.FindLastOf(_T("/\\")); + size_t stEnd = m_pPath->m_strPath.FindLastOf(_T(".")); + if((stStart == TString::npos && stEnd == TString::npos)) return !IsEmpty(); - if(stStart == std::wstring::npos) // if does not exist, start from beginning + if(stStart == TString::npos) // if does not exist, start from beginning stStart = 0; - if(stEnd == std::wstring::npos || stEnd < stStart) // if does not exist or we have ".\\", use up to the end - stEnd = m_pPath->m_strPath.length(); + if(stEnd == TString::npos || stEnd < stStart) // if does not exist or we have ".\\", use up to the end + stEnd = m_pPath->m_strPath.GetLength(); return stEnd > stStart + 1; } @@ -801,17 +804,16 @@ if(!m_pPath) return TSmartPath(); - size_t stStart = m_pPath->m_strPath.find_last_of(_T("/\\")); - size_t stEnd = m_pPath->m_strPath.find_last_of(_T(".")); - if((stStart == std::wstring::npos && stEnd == std::wstring::npos)) + size_t stStart = m_pPath->m_strPath.FindLastOf(_T("/\\")); + size_t stEnd = m_pPath->m_strPath.FindLastOf(_T(".")); + if((stStart == TString::npos && stEnd == TString::npos)) return *this; - if(stStart == std::wstring::npos) // if does not exist, start from beginning + if(stStart == TString::npos) // if does not exist, start from beginning stStart = 0; - if(stEnd == std::wstring::npos || stEnd < stStart) // if does not exist or we have ".\\", use up to the end - stEnd = m_pPath->m_strPath.length(); + if(stEnd == TString::npos || stEnd < stStart) // if does not exist or we have ".\\", use up to the end + stEnd = m_pPath->m_strPath.GetLength(); - std::wstring wstrDir(m_pPath->m_strPath.begin() + stStart + 1, m_pPath->m_strPath.begin() + stEnd); - return PathFromWString(wstrDir); + return PathFromWString(m_pPath->m_strPath.MidByPos(stStart + 1, stEnd)); } // ============================================================================ @@ -826,9 +828,9 @@ if(!m_pPath) return false; - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/.")); + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/.")); - return stIndex != std::wstring::npos && (m_pPath->m_strPath.at(stIndex) == _T('.')); + return stIndex != TString::npos && (m_pPath->m_strPath.GetAt(stIndex) == _T('.')); } // ============================================================================ @@ -843,10 +845,10 @@ if(!m_pPath) return TSmartPath(); - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/.")); + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/.")); - if(stIndex != std::wstring::npos && m_pPath->m_strPath.at(stIndex) == _T('.')) - return PathFromWString(std::wstring(m_pPath->m_strPath.begin() + stIndex, m_pPath->m_strPath.end())); // ".txt" for "c:\windows\test.txt" + if(stIndex != TString::npos && m_pPath->m_strPath.GetAt(stIndex) == _T('.')) + return PathFromWString(m_pPath->m_strPath.MidByPos(stIndex, m_pPath->m_strPath.GetLength())); // ".txt" for "c:\windows\test.txt" return TSmartPath(); } @@ -863,8 +865,8 @@ if(!m_pPath) return false; - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - return (stIndex != std::wstring::npos && stIndex != m_pPath->m_strPath.length() - 1); + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + return (stIndex != TString::npos && stIndex != m_pPath->m_strPath.GetLength() - 1); } // ============================================================================ @@ -879,9 +881,9 @@ if(!m_pPath) return TSmartPath(); - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - if(stIndex != std::wstring::npos) - return PathFromWString(std::wstring(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end())); // "test.txt" for "c:\windows\test.txt" + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + if(stIndex != TString::npos) + return PathFromWString(m_pPath->m_strPath.MidByPos(stIndex + 1, m_pPath->m_strPath.GetLength())); // "test.txt" for "c:\windows\test.txt" return TSmartPath(); } @@ -897,11 +899,11 @@ if(!m_pPath) return; - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - if(stIndex != std::wstring::npos) + size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/")); + if(stIndex != TString::npos) { PrepareToWrite(); - m_pPath->m_strPath.erase(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end()); // "test.txt" for "c:\windows\test.txt" + m_pPath->m_strPath.Delete(stIndex + 1, m_pPath->m_strPath.GetLength() - stIndex - 1); // "test.txt" for "c:\windows\test.txt" } } @@ -917,10 +919,10 @@ if(!m_pPath) return false; - size_t stThisSize = m_pPath->m_strPath.length(); + size_t stThisSize = m_pPath->m_strPath.GetLength(); if(stThisSize > 0) { - wchar_t wchLastChar = m_pPath->m_strPath.at(stThisSize - 1); + wchar_t wchLastChar = m_pPath->m_strPath.GetAt(stThisSize - 1); return (wchLastChar == _T('\\') || wchLastChar == _T('/')); } @@ -953,7 +955,7 @@ if(EndsWithSeparator()) { PrepareToWrite(); - m_pPath->m_strPath.erase(m_pPath->m_strPath.end() - 1); + m_pPath->m_strPath.DeleteChar(m_pPath->m_strPath.GetLength() - 1); } } @@ -970,8 +972,8 @@ return false; wchar_t wchLastChar = 0; - if(m_pPath->m_strPath.length() > 0) - wchLastChar = m_pPath->m_strPath.at(0); + if(m_pPath->m_strPath.GetLength() > 0) + wchLastChar = m_pPath->m_strPath.GetAt(0); return (wchLastChar == _T('\\') || wchLastChar == _T('/')); } @@ -987,7 +989,7 @@ if(!StartsWithSeparator()) { PrepareToWrite(); - m_pPath->m_strPath.insert(0, _T("\\")); + m_pPath->m_strPath = _T("\\") + m_pPath->m_strPath; } } @@ -1003,7 +1005,7 @@ { PrepareToWrite(); - m_pPath->m_strPath.erase(0); + m_pPath->m_strPath.DeleteChar(0); } } @@ -1015,7 +1017,7 @@ // ============================================================================ bool TSmartPath::IsEmpty() const { - return !m_pPath || m_pPath->m_strPath.empty(); + return !m_pPath || m_pPath->m_strPath.IsEmpty(); } // ============================================================================ @@ -1029,7 +1031,7 @@ { if(!m_pPath) return 0; - return m_pPath->m_strPath.length(); + return m_pPath->m_strPath.GetLength(); } // ============================================================================ @@ -1042,7 +1044,7 @@ // ============================================================================ void TSmartPath::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszPropName) const { - rConfig.SetValue(pszPropName, m_pPath ? m_pPath->m_strPath : std::wstring()); + rConfig.SetValue(pszPropName, m_pPath ? m_pPath->m_strPath : TString()); } // ============================================================================ @@ -1056,7 +1058,7 @@ // ============================================================================ bool TSmartPath::ReadFromConfig(const chcore::TConfig& rConfig, PCTSTR pszPropName) { - std::wstring wstrPath; + TString wstrPath; if(rConfig.GetValue(pszPropName, wstrPath)) { PrepareToWrite(); @@ -1126,7 +1128,7 @@ /// @param[in] pszPath - string containing path. /// @return New path object. // ============================================================================ -TSmartPath PathFromWString(const std::wstring& strPath) +TSmartPath PathFromWString(const TString& strPath) { TSmartPath spPath; spPath.FromString(strPath); @@ -1294,12 +1296,12 @@ void TPathContainer::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszPropName) const { - std::vector vPaths; + TStringArray vPaths; // store as vector of strings (ineffective; should be done better) BOOST_FOREACH(const TSmartPath& spPath, m_vPaths) { - vPaths.push_back(spPath.ToWString()); + vPaths.Add(spPath.ToWString()); } rConfig.SetValue(pszPropName, vPaths); @@ -1309,12 +1311,12 @@ { m_vPaths.clear(); - std::vector vPaths; + TStringArray vPaths; if(rConfig.GetValue(pszPropName, vPaths)) { - BOOST_FOREACH(const std::wstring& wstrPath, vPaths) + for(size_t stIndex = 0; stIndex < vPaths.GetCount(); ++stIndex) { - m_vPaths.push_back(PathFromWString(wstrPath)); + m_vPaths.push_back(PathFromWString(vPaths.GetAt(stIndex))); } return true; } Index: src/libchcore/TPath.h =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TPath.h (.../TPath.h) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/TPath.h (.../TPath.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -44,7 +44,7 @@ protected: #pragma warning(push) #pragma warning(disable: 4251) - std::wstring m_strPath; + TString m_strPath; #pragma warning(pop) long m_lRefCount; @@ -75,10 +75,10 @@ // from/to string conversions void FromString(const wchar_t* pszPath); - void FromString(const std::wstring& strPath); + void FromString(const TString& strPath); const wchar_t* ToString() const; - std::wstring ToWString() const; + TString ToWString() const; // other operations void Clear() throw(); @@ -165,7 +165,7 @@ }; LIBCHCORE_API TSmartPath PathFromString(const wchar_t* pszPath); -LIBCHCORE_API TSmartPath PathFromWString(const std::wstring& strPath); +LIBCHCORE_API TSmartPath PathFromWString(const TString& strPath); class LIBCHCORE_API TPathContainer { Index: src/libchcore/TSharedMemory.cpp =================================================================== diff -u -N --- src/libchcore/TSharedMemory.cpp (revision 0) +++ src/libchcore/TSharedMemory.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,262 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TSharedMemory.cpp +/// @date 2011/05/03 +/// @brief Contains implementation of shared memory handling classes. +// ============================================================================ +#include "stdafx.h" +#include "TSharedMemory.h" +#include +#include "TWStringData.h" +#include "ErrorCodes.h" + +BEGIN_CHCORE_NAMESPACE + +#define MUTEX_SUFFIX _T("_Mutex") + +class TMutexLock +{ +public: + TMutexLock(HANDLE hMutex) : + m_hMutex(hMutex) + { + if(m_hMutex) + { + DWORD dwRes = WaitForSingleObject(hMutex, 10000); + if(dwRes != WAIT_OBJECT_0) + THROW_CORE_EXCEPTION(eMutexTimedOut); + } + } + + ~TMutexLock() + { + if(m_hMutex) + ReleaseMutex(m_hMutex); + } + +private: + HANDLE m_hMutex; +}; + +/////////////////////////////////////////////////////////////////////////////////////// +// TSharedMemory class + +TSharedMemory::TSharedMemory() : + m_hFileMapping(NULL), + m_pMappedMemory(NULL), + m_hMutex(NULL), + m_stSize(0) +{ +} + +TSharedMemory::~TSharedMemory() +{ + Close(); +} + +void TSharedMemory::Create(const wchar_t* pszName, size_t stSize) +{ + if(!pszName || pszName[0] == _T('\0') || stSize == 0) + THROW_CORE_EXCEPTION(eInvalidArgument); + + Close(); + + try + { + std::wstring wstrMutexName = pszName; + wstrMutexName += MUTEX_SUFFIX; + + SECURITY_DESCRIPTOR secDesc; + if(!InitializeSecurityDescriptor(&secDesc, SECURITY_DESCRIPTOR_REVISION)) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + + SECURITY_ATTRIBUTES secAttr; + secAttr.nLength = sizeof(secAttr); + secAttr.bInheritHandle = FALSE; + secAttr.lpSecurityDescriptor = &secDesc; + + if(!SetSecurityDescriptorDacl(secAttr.lpSecurityDescriptor, TRUE, 0, FALSE)) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + + m_hMutex = ::CreateMutex(&secAttr, FALSE, wstrMutexName.c_str()); + if(!m_hMutex) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + + m_hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, 0, boost::numeric_cast(stSize + sizeof(size_t)), pszName); + if(!m_hFileMapping) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + else if(GetLastError() == ERROR_ALREADY_EXISTS) + THROW_CORE_EXCEPTION(eSharedMemoryAlreadyExists); // shared memory already exists - cannot guarantee that the size is correct + + // Get a pointer to the file-mapped shared memory. + m_pMappedMemory = (BYTE*)MapViewOfFile(m_hFileMapping, FILE_MAP_WRITE, 0, 0, 0); + if(!m_pMappedMemory) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + } + catch(...) + { + Close(); + throw; + } + + TMutexLock lock(m_hMutex); + + m_stSize = stSize + sizeof(size_t); + *(size_t*)m_pMappedMemory = sizeof(size_t); // no data inside (set just in case) +} + +void TSharedMemory::Create(const wchar_t* pszName, const TWStringData& wstrData) +{ + Create(pszName, (BYTE*)wstrData.GetData(), wstrData.GetBytesCount()); +} + +void TSharedMemory::Create(const wchar_t* pszName, const BYTE* pbyData, size_t stSize) +{ + Create(pszName, stSize); + + TMutexLock lock(m_hMutex); + + *(size_t*)m_pMappedMemory = stSize; + memcpy(m_pMappedMemory + sizeof(size_t), pbyData, stSize); +} + +void TSharedMemory::Open(const wchar_t* pszName) +{ + Close(); + + try + { + m_hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE, pszName); + if(!m_hFileMapping) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + + // Get a pointer to the file-mapped shared memory. + m_pMappedMemory = (BYTE*)MapViewOfFile(m_hFileMapping, FILE_MAP_READ, 0, 0, 0); + if(!m_pMappedMemory) + THROW_CORE_EXCEPTION(eCannotOpenSharedMemory); + } + catch(...) + { + Close(); + throw; + } + + TMutexLock lock(m_hMutex); + + m_stSize = *(size_t*)m_pMappedMemory + sizeof(size_t); +} + +void TSharedMemory::Close() throw() +{ + try + { + if(m_hMutex) + { + CloseHandle(m_hMutex); + m_hMutex = NULL; + } + + if(m_pMappedMemory) + { + UnmapViewOfFile(m_pMappedMemory); + m_pMappedMemory = NULL; + } + + // Close the process's handle to the file-mapping object. + if(m_hFileMapping) + { + CloseHandle(m_hFileMapping); + m_hFileMapping = NULL; + } + } + catch(...) + { + } +} + +void TSharedMemory::Read(TWStringData& wstrData) const +{ + if(!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(size_t)) + THROW_CORE_EXCEPTION(eSharedMemoryNotOpen); + + TMutexLock lock(m_hMutex); + + size_t stByteSize = *(size_t*)m_pMappedMemory; + if((stByteSize % 2) != 0) + THROW_CORE_EXCEPTION(eSharedMemoryInvalidFormat); + + const wchar_t* pszRealData = (const wchar_t*)(m_pMappedMemory + sizeof(size_t)); + size_t stCharCount = stByteSize / 2; + + if(pszRealData[stCharCount - 1] != _T('\0')) + THROW_CORE_EXCEPTION(eSharedMemoryInvalidFormat); + + wstrData = pszRealData; +} + +void TSharedMemory::Write(const TWStringData& wstrData) +{ + Write((BYTE*)wstrData.GetData(), wstrData.GetBytesCount()); +} + +void TSharedMemory::Write(const BYTE* pbyData, size_t stSize) +{ + if(stSize + sizeof(size_t) > m_stSize) + THROW_CORE_EXCEPTION(eBoundsExceeded); + + TMutexLock lock(m_hMutex); + + *(size_t*)m_pMappedMemory = stSize; + memcpy(m_pMappedMemory + sizeof(size_t), pbyData, stSize); +} + +const BYTE* TSharedMemory::GetData() const +{ + if(!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(size_t)) + return NULL; + + return (BYTE*)m_pMappedMemory + sizeof(size_t); +} + +BYTE* TSharedMemory::GetData() +{ + if(!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(size_t)) + return NULL; + + return (BYTE*)m_pMappedMemory + sizeof(size_t); +} + +size_t TSharedMemory::GetSharedMemorySize() const +{ + if(!m_hFileMapping || !m_pMappedMemory) + return 0; + return m_stSize; +} + +size_t TSharedMemory::GetDataSize() const +{ + if(!m_hFileMapping || !m_pMappedMemory || m_stSize <= sizeof(size_t)) + return 0; + + TMutexLock lock(m_hMutex); + + return *(size_t*)m_pMappedMemory; +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TSharedMemory.h =================================================================== diff -u -N --- src/libchcore/TSharedMemory.h (revision 0) +++ src/libchcore/TSharedMemory.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,64 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TSharedMemory.h +/// @date 2011/05/03 +/// @brief Contains shared memory support classes. +// ============================================================================ +#ifndef __TSHAREDMEMORY_H__ +#define __TSHAREDMEMORY_H__ + +BEGIN_CHCORE_NAMESPACE + +class TWStringData; + +class LIBCHCORE_API TSharedMemory +{ +public: + TSharedMemory(); + ~TSharedMemory(); + + void Create(const wchar_t* pszName, size_t stSize); + void Create(const wchar_t* pszName, const TWStringData& wstrData); + void Create(const wchar_t* pszName, const BYTE* pbyData, size_t stSize); + + void Open(const wchar_t* pszName); + void Close() throw(); + + void Read(TWStringData& wstrData) const; + void Write(const TWStringData& wstrData); + void Write(const BYTE* pbyData, size_t stSize); + + // below are the unsafe functions (i.e. not protected with mutex) + const BYTE* GetData() const; + BYTE* GetData(); + + size_t GetSharedMemorySize() const; + size_t GetDataSize() const; + +private: + HANDLE m_hFileMapping; + BYTE* m_pMappedMemory; + size_t m_stSize; // contains full size of the allocated shared memory (in case we created the memory), size of occupied memory in case we opened the memory. + + HANDLE m_hMutex; +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TString.cpp =================================================================== diff -u -N --- src/libchcore/TString.cpp (revision 0) +++ src/libchcore/TString.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,767 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TString.cpp +/// @date 2011/06/05 +/// @brief Contains implementation of TString class. +// ============================================================================ +#include "stdafx.h" +#include "TString.h" +#include +#pragma warning(push) +#pragma warning(disable: 4996) // boost::split uses unsafe std::copy + #include +#pragma warning(pop) +#include "TStringArray.h" + +/// Rounding up value to the nearest chunk multiplicity +#define ROUNDUP(val,chunk) ((val + chunk - 1) & ~(chunk-1)) + +///< Increment value for internal TString buffer +#define CHUNK_INCSIZE 64 + +// if (buffer_size-string_size > CHUNK_DECSIZE) then the buffer will be shrinked +///< Difference value above which the TString will be shrinked +#define CHUNK_DECSIZE 256 + +BEGIN_CHCORE_NAMESPACE + +namespace details +{ + TInternalStringData* TInternalStringData::Allocate(size_t stBufferSize) + { + if(stBufferSize == 0) + stBufferSize = 1; + + // calculate the real buffer size to be allocated + size_t stRealBufferSize = stBufferSize * sizeof(wchar_t) + sizeof(TInternalStringData); + stRealBufferSize = ROUNDUP(stRealBufferSize, CHUNK_INCSIZE); + + // initialize the newly created TInternalStringData + TInternalStringData* pNewData = (TInternalStringData*)new BYTE[stRealBufferSize]; + pNewData->m_lRefCount = 0; + pNewData->m_stBufferSize = (stRealBufferSize - sizeof(TInternalStringData)) / sizeof(wchar_t); + pNewData->m_stStringLength = 0; + + // nullify the string, so it appear empty + pNewData->GetData()[0] = _T('\0'); + + return pNewData; + } + + void TInternalStringData::Free(TInternalStringData* pStringData) + { + if(pStringData) + delete [] (BYTE*)pStringData; + } + + TInternalStringData* TInternalStringData::Clone() + { + TInternalStringData* pStringData = TInternalStringData::Allocate(m_stBufferSize); + BOOST_ASSERT(m_stBufferSize == pStringData->m_stBufferSize); + + wcsncpy_s(pStringData->GetData(), pStringData->m_stBufferSize, GetData(), m_stStringLength + 1); + pStringData->m_stStringLength = m_stStringLength; + + return pStringData; + } + + TInternalStringData* TInternalStringData::CloneWithResize(size_t stNewSize) + { + TInternalStringData* pStringData = TInternalStringData::Allocate(stNewSize); + + size_t stDataToCopy = min(pStringData->m_stBufferSize - 1, m_stStringLength); + + // copy as much data from the current buffer as possible + wcsncpy_s(pStringData->GetData(), pStringData->m_stBufferSize, GetData(), stDataToCopy); + // and ensure we always have proper string termination + pStringData->GetData()[stDataToCopy] = _T('\0'); + + pStringData->m_stStringLength = stDataToCopy; + + return pStringData; + } + + TInternalStringData* TInternalStringData::CloneIfShared(bool& bCloned) + { + if(m_lRefCount > 1) + { + bCloned = true; + return Clone(); + } + else + { + bCloned = false; + return this; + } + } +} + +using namespace details; + +size_t TString::npos = (size_t)-1; + +/** Standard constructor - allocates the underlying data object + */ +TString::TString() : + m_pszStringData(NULL) +{ +} + +/** Constructor allocates the underlying data object and initializes it with + * a given unicode TString. + * \param[in] pszStr - source unicode TString + */ +TString::TString(const wchar_t* pszStr) : + m_pszStringData(NULL) +{ + SetString(pszStr); +} + +TString::TString(const wchar_t* pszStart, const wchar_t* pszEnd) : + m_pszStringData(NULL) +{ + SetString(pszStart, pszEnd - pszStart); +} + +TString::TString(const wchar_t* pszStart, size_t stCount) : + m_pszStringData(NULL) +{ + SetString(pszStart, stCount); +} + +/** Constructor increases the reference count in the parameter's data object + * and copies only the data object address. + * \param[in] str - source TString object + */ +TString::TString(const TString& str) : + m_pszStringData(str.m_pszStringData) +{ + AddRef(); +} + +/** Destructor releases the underlying data object. + */ +TString::~TString() +{ + try + { + Release(); + } + catch(...) + { + } +} + +/** Operator releases the current data object, stores a pointer to + * the data object from the given TString object and increases a reference + * count. + * \param[in] src - source TString object + * \return A reference to the current TString. + */ +const TString& TString::operator=(const TString& rSrc) +{ + if(this != &rSrc) + { + Release(); + + m_pszStringData = rSrc.m_pszStringData; + AddRef(); + } + + return *this; +} + +/** Operator makes an own copy of underlying data object (if needed) and copy + * there the given unicode TString. + * \param[in] pszSrc - source unicode TString + * \return A reference to the current TString object. + */ +const TString& TString::operator=(const wchar_t* pszSrc) +{ + if(m_pszStringData != pszSrc) + SetString(pszSrc); + + return *this; +} + +/** Operator concatenates a given TString object with the current content of + * this TString and returns a new TString object. + * \param[in] src - TString object that will be appended + * \return A new TString object with concatenated strings. + */ +const TString TString::operator+(const TString& src) const +{ + TString str(*this); + str.Append(src); + + return str; +} + +/** Operator concatenates a given unicode TString with the current content of + * this TString and returns a new TString object. + * \param[in] pszSrc - unicode TString that will be appended + * \return A new TString object with concatenated strings. + */ +const TString TString::operator+(const wchar_t* pszSrc) const +{ + TString str(*this); + str.Append(pszSrc); + + return str; +} + +/** Operator appends a given TString object to own internal buffer. + * \param[in] src - TString object that will be appended + * \return A reference to this. + */ +const TString& TString::operator+=(const TString& src) +{ + Append(src); + return *this; +} + +/** Operator appends a given unicode TString to own internal buffer. + * \param[in] pszSrc - unicode TString that will be appended + * \return A reference to this. + */ +const TString& TString::operator+=(const wchar_t* pszSrc) +{ + Append(pszSrc); + return *this; +} + +/** Function counts the GetLength of a TString in characters (doesn't matter if the TString + * is unicode or ansi). + * \note All GetLength checks should be done through this function, because of possible future + * update that will store the TString GetLength in the internal member. + * \return The TString GetLength in characters, not including the terminating '\\0' + */ +size_t TString::GetLength() const +{ + if(m_pszStringData) + return GetInternalStringData()->GetStringLength(); + else + return 0; +} + +/** Function makes own data object writable and clears it. Does not delete the + * internal buffer - only sets the content to '\\0'. + */ +void TString::Clear() +{ + // make sure we have the modifiable object without allocated TString buffer + Release(); +} + +/** Function checks if the TString is empty. + * \return True if this TString is empty, false otherwise. + */ +bool TString::IsEmpty() const +{ + return !m_pszStringData || m_pszStringData[0] == _T('\0'); +} + +/** Function merges the given unicode TString with the current content of an internal buffer. + * \param[in] pszSrc - unicode TString to append + */ +void TString::Append(const wchar_t* pszSrc) +{ + if(!pszSrc) + return; + + size_t stCurrentLen = GetLength(); + size_t stAddLen = wcslen(pszSrc); + EnsureWritable(stCurrentLen + stAddLen + 1); + + wcsncpy_s(m_pszStringData + stCurrentLen, GetCurrentBufferSize() - stCurrentLen, pszSrc, stAddLen + 1); + GetInternalStringData()->SetStringLength(stCurrentLen + stAddLen); +} + +/** Function merges the given TString object with the current content of an internal buffer. + * \param[in] src - TString object to append + */ +void TString::Append(const TString& rSrc) +{ + if(rSrc.IsEmpty()) + return; + + size_t stCurrentLen = GetLength(); + size_t stAddLen = rSrc.GetLength(); + EnsureWritable(stCurrentLen + stAddLen + 1); + + wcsncpy_s(m_pszStringData + stCurrentLen, GetCurrentBufferSize() - stCurrentLen, rSrc.m_pszStringData, stAddLen + 1); + GetInternalStringData()->SetStringLength(stCurrentLen + stAddLen); +} + +/** Returns a new TString object with the Left part of this TString object. + * \param[in] tLen - count of characters to copy to the new TString object + * \return The TString with the Left part of the current TString. + */ +TString TString::Left(size_t tLen) const +{ + if(!m_pszStringData || tLen == 0) + return TString(); + + size_t stCurrentLength = GetLength(); + + if(tLen >= stCurrentLength) + return *this; + else + return TString(m_pszStringData, tLen); +} + +/** Returns a new TString object with the Right part of this TString object. + * \param[in] tLen - count of characters to copy to the new TString object + * \return The TString with the Right part of the current TString. + */ +TString TString::Right(size_t tLen) const +{ + if(!m_pszStringData || tLen == 0) + return TString(); + + size_t stCurrentLen = GetLength(); + if(tLen >= stCurrentLen) + return *this; + else + return TString(m_pszStringData + stCurrentLen - tLen, tLen); +} + +/** Returns a new TString object with the middle part of this TString object. + * \param[in] tStart - position of the first character to copy + * \param[in] tLen - count of chars to copy + * \return The TString with the middle part of the current TString. + */ +TString TString::Mid(size_t tStart, size_t tLen) const +{ + if(!m_pszStringData || tLen == 0) + return TString(); + + size_t stCurrentLength = GetLength(); + if(tStart >= stCurrentLength) + return TString(); + + size_t stRealLength = min(tLen, stCurrentLength - tStart); + + TString strNew(m_pszStringData + tStart, stRealLength); + + return strNew; +} + +TString TString::MidByPos(size_t tStart, size_t stAfterEndPos) const +{ + return Mid(tStart, stAfterEndPos - tStart); +} + +/** Makes this TString it's Left part. Much faster than using standard + * Left() function. + * \param[in] tLen - count of characters at the beginning of the TString to be Left in a TString. + * \param[in] bReallocBuffer - if the internal TString buffer is to be reallocated if exceeds + * the allowable range size (CHUNK_INCSIZE, CHUNK_DECSIZE). + * \see Left() + */ +void TString::LeftSelf(size_t tLen) +{ + // nothing to do if nothing inside + if(!m_pszStringData) + return; + + size_t stCurrentLength = GetLength(); + if(tLen < stCurrentLength) // otherwise there is nothing to do + { + EnsureWritable(tLen + 1); + m_pszStringData[tLen] = _T('\0'); + GetInternalStringData()->SetStringLength(tLen); + } +} + +/** Makes this TString it's Right part. Much faster than using standard + * Right() function. + * \param[in] tLen - count of characters at the end of the TString to be Left in a TString. + * \param[in] bReallocBuffer - if the internal TString buffer is to be reallocated if exceeds + * the allowable range size (CHUNK_INCSIZE, CHUNK_DECSIZE). + * \see Right() + */ +void TString::RightSelf(size_t tLen) +{ + // nothing to do if nothing inside + if(!m_pszStringData) + return; + + size_t stCurrentLength = GetLength(); + if(tLen < stCurrentLength) // otherwise there is nothing to do + { + EnsureWritable(stCurrentLength + 1); + + wmemmove(m_pszStringData, m_pszStringData + stCurrentLength - tLen, tLen + 1); + GetInternalStringData()->SetStringLength(tLen); + } +} + +/** Makes this TString it's middle part. Much faster than using standard + * Mid() function. + * \param[in] tStart - starting position of a text to be Left in a TString + * \param[in] tLen - count of characters at the middle of the TString to be Left in a TString. + * \param[in] bReallocBuffer - if the internal TString buffer is to be reallocated if exceeds + * the allowable range size (CHUNK_INCSIZE, CHUNK_DECSIZE). + * \see Mid() + */ +void TString::MidSelf(size_t tStart, size_t tLen) +{ + if(!m_pszStringData) + return; + + size_t stCurrentLength = GetLength(); + if(tStart >= stCurrentLength) + { + EnsureWritable(1); + m_pszStringData[0] = _T('\0'); + GetInternalStringData()->SetStringLength(0); + } + else + { + size_t stRealLength = min(tLen, stCurrentLength - tStart); + + EnsureWritable(stRealLength + 1); + wmemmove(m_pszStringData, m_pszStringData + tStart, stRealLength); + m_pszStringData[stRealLength] = _T('\0'); + + GetInternalStringData()->SetStringLength(stRealLength); + } +} + +void TString::DeleteChar(size_t stIndex) +{ + size_t stCurrentLength = GetLength(); + if(stIndex >= stCurrentLength) + return; + + EnsureWritable(1); + wmemmove(m_pszStringData + stIndex, m_pszStringData + stIndex + 1, stCurrentLength - stIndex); + GetInternalStringData()->SetStringLength(stCurrentLength - 1); +} + +void TString::Delete(size_t stIndex, size_t stCount) +{ + size_t stCurrentLength = GetLength(); + if(stIndex >= stCurrentLength) + return; + + EnsureWritable(stCurrentLength + 1); + + size_t stCountToDelete = min(stCurrentLength - stIndex, stCount); + + wmemmove(m_pszStringData + stIndex, m_pszStringData + stIndex + stCountToDelete, stCountToDelete); + GetInternalStringData()->SetStringLength(stCurrentLength - stCountToDelete); +} + +void TString::Split(const wchar_t* pszSeparators, TStringArray& rStrings) const +{ + rStrings.Clear(); + if(!m_pszStringData || !pszSeparators) + return; + + // ugly version - many reallocations due to the usage of stl wstrings + std::vector vStrings; + boost::split(vStrings, m_pszStringData, boost::is_any_of(pszSeparators)); + + BOOST_FOREACH(const std::wstring& strPart, vStrings) + { + rStrings.Add(strPart.c_str()); + } + +} + +/** Compares a TString with the given unicode TString. Comparison is case sensitive. + * \param[in] psz - unicode TString to which the TString object will be compared + * \return <0 if this TString object is "less" than psz, 0 if they are equal and >0 otherwise. + */ +int_t TString::Compare(const wchar_t* psz) const +{ + if(psz == m_pszStringData) + return 0; + else + { + if(psz == NULL || m_pszStringData == NULL) + return m_pszStringData == NULL ? -1 : 1; + else + return wcscmp(m_pszStringData, psz); + } +} + +/** Compares a TString with the given TString object. Comparison is case sensitive. + * \param[in] str - TString object to which internal TString object will be compared + * \return <0 if this TString object is "less" than psz, 0 if they are equal and >0 otherwise. + */ +int_t TString::Compare(const TString& str) const +{ + if(str.m_pszStringData == m_pszStringData) + return 0; + else + { + if(str.m_pszStringData == NULL || m_pszStringData == NULL) + return m_pszStringData == NULL ? -1 : 1; + else + return wcscmp(m_pszStringData, str.m_pszStringData); + } +} + +/** Compares a TString with the given unicode TString. Comparison is case insensitive. + * \param[in] psz - unicode TString to which internal TString object will be compared + * \return <0 if this TString object is "less" than psz, 0 if they are equal and >0 otherwise. + */ +int_t TString::CompareNoCase(const wchar_t* psz) const +{ + if(psz == m_pszStringData) + return 0; + else + { + if(psz == NULL || m_pszStringData == NULL) + return m_pszStringData == NULL ? -1 : 1; + else + return _wcsicmp(m_pszStringData, psz); + } +} + +/** Compares a TString with the given TString object. Comparison is case insensitive. + * \param[in] str - TString object to which internal TString object will be compared + * \return <0 if this TString object is "less" than str, 0 if they are equal and >0 otherwise. + */ +int_t TString::CompareNoCase(const TString& str) const +{ + if(str.m_pszStringData == m_pszStringData) + return 0; + else + { + if(str.m_pszStringData == NULL || m_pszStringData == NULL) + return m_pszStringData == NULL ? -1 : 1; + else + return _wcsicmp(m_pszStringData, str.m_pszStringData); + } +} + +bool TString::StartsWith(const wchar_t* pszText) const +{ + if(!m_pszStringData || !pszText) + return false; + + return boost::starts_with(m_pszStringData, pszText); +} + +bool TString::StartsWithNoCase(const wchar_t* pszText) const +{ + if(!m_pszStringData || !pszText) + return false; + + return boost::istarts_with(m_pszStringData, pszText); +} + +bool TString::EndsWith(const wchar_t* pszText) const +{ + if(!m_pszStringData || !pszText) + return false; + + return boost::ends_with(m_pszStringData, pszText); +} + +bool TString::EndsWithNoCase(const wchar_t* pszText) const +{ + if(!m_pszStringData || !pszText) + return false; + + return boost::iends_with(m_pszStringData, pszText); +} + +size_t TString::FindFirstOf(const wchar_t* pszChars, size_t stStartFromPos) const +{ + if(!m_pszStringData || !pszChars) + return npos; + + size_t stCurrentLength = GetLength(); + for(size_t stIndex = stStartFromPos; stIndex < stCurrentLength; ++stIndex) + { + if(wcschr(pszChars, m_pszStringData[stIndex])) + return stIndex; + } + + return npos; +} + +size_t TString::FindLastOf(const wchar_t* pszChars) const +{ + if(!m_pszStringData || !pszChars) + return npos; + + for(size_t stIndex = GetLength(); stIndex != 0; --stIndex) + { + if(wcschr(pszChars, m_pszStringData[stIndex - 1])) + return stIndex - 1; + } + + return npos; +} + +/** Returns a character at a given position. Function is very slow (needs to recalc the size of the TString + * and make a few comparisons), but quite safe - if the index is out of range then -1 is returned. + * Make sure to interpret the returned character according to unicode flag. If the TString is unicode, then the + * character returned is also unicode (and vice versa). + * \param[in] tPos - index of the character to return. + * \return Character code of character on a specified position, or -1 if out of range. + */ +bool TString::GetAt(size_t tPos, wchar_t& wch) const +{ + size_t tSize = GetLength(); + if(tPos < tSize) + { + wch = m_pszStringData[tPos]; + return true; + } + else + return false; +} + +wchar_t TString::GetAt(size_t tPos) const +{ + size_t tSize = GetLength(); + if(tPos < tSize) + return m_pszStringData[tPos]; + else + { + BOOST_ASSERT(tPos >= tSize); + // would be nice to throw an exception here + return L'\0'; + } +} + +/** Returns a pointer to the unicode internal buffer. If the buffer is in ansi format + * then NULL value is returned. Internal buffer is resized to the specified value + * if currently smaller than requested (if -1 is specified as tMinSize then the buffer + * is not resized, and the return value could be NULL). + * \param[in] tMinSize - requested minimal size of the internal buffer (-1 if the size of the TString should not be changed) + * \return Pointer to the internal unicode buffer. + */ +wchar_t* TString::GetBuffer(size_t tMinSize) +{ + EnsureWritable(tMinSize); + return m_pszStringData; +} + +/** Releases buffer got by user by calling get_bufferx functions. The current + * job of this function is to make sure the TString will terminate with null + * character at the end of the buffer. + */ +void TString::ReleaseBuffer() +{ + EnsureWritable(1); + + m_pszStringData[GetCurrentBufferSize() - 1] = L'\0'; + GetInternalStringData()->SetStringLength(wcslen(m_pszStringData)); +} + +void TString::ReleaseBufferSetLength(size_t tSize) +{ + EnsureWritable(tSize + 1); + + m_pszStringData[GetCurrentBufferSize() - 1] = L'\0'; + GetInternalStringData()->SetStringLength(tSize); +} + +/** Cast operator - tries to return a pointer to wchar_t* using the current internal + * buffer. If the internal buffer is in ansi format, then the debug version asserts + * and release return NULL. + * \return Pointer to an unicode TString (could be null). + */ +TString::operator const wchar_t*() const +{ + return m_pszStringData ? m_pszStringData : L""; +} + +/** Function makes the internal data object writable, copies the given unicode TString into + * the internal TString buffer and sets the unicode flag if needed. + * \param[in] pszStr - source unicode TString + */ +void TString::SetString(const wchar_t* pszStr) +{ + if(!pszStr) + SetString(_T("")); + else + { + size_t stStringLen = wcslen(pszStr); + EnsureWritable(stStringLen + 1); + + wcsncpy_s(m_pszStringData, GetCurrentBufferSize(), pszStr, stStringLen + 1); + GetInternalStringData()->SetStringLength(stStringLen); + } +} + +void TString::SetString(const wchar_t* pszStart, size_t stCount) +{ + if(!pszStart || stCount == 0) + SetString(_T("")); + else + { + EnsureWritable(stCount + 1); + + wcsncpy_s(m_pszStringData, GetCurrentBufferSize() - 1, pszStart, stCount); + m_pszStringData[stCount] = _T('\0'); + GetInternalStringData()->SetStringLength(stCount); + } +} + +void TString::EnsureWritable(size_t stRequestedSize) +{ + // NOTE: when stRequestedSize is 0, we want to preserve current buffer size + TInternalStringData* pInternalStringData = GetInternalStringData(); + if(!pInternalStringData) + { + pInternalStringData = TInternalStringData::Allocate(stRequestedSize); + m_pszStringData = pInternalStringData->GetData(); + AddRef(); + } + else if(stRequestedSize <= GetCurrentBufferSize()) + { + // no need to resize - just ensuring that we have the exclusive ownership is enough + bool bCloned = false; + TInternalStringData* pNewData = pInternalStringData->CloneIfShared(bCloned); + if(bCloned) + { + Release(); + + m_pszStringData = pNewData->GetData(); + AddRef(); + } + } + else + { + // need to resize + TInternalStringData* pNewData = pInternalStringData->CloneWithResize(stRequestedSize); + Release(); + + m_pszStringData = pNewData->GetData(); + AddRef(); + } +} + +END_CHCORE_NAMESPACE + +chcore::TString operator+(const wchar_t* pszString, chcore::TString& str) +{ + chcore::TString strNew(pszString); + strNew += str; + return strNew; +} Index: src/libchcore/TString.h =================================================================== diff -u -N --- src/libchcore/TString.h (revision 0) +++ src/libchcore/TString.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,278 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TString.h +/// @date 2011/06/05 +/// @brief Contains declaration of TString class. +// ============================================================================ +#ifndef __TSTRING_H__ +#define __TSTRING_H__ + +#include "libchcore.h" +#include + +BEGIN_CHCORE_NAMESPACE + +class TStringArray; + +////////////////////////////////////////////////////////////// +// EnsureExclusiveOwnership flags +/// Standard - makes a copy of an underlying object if reference count >1 +#define MWF_COPY 0x00000000 +/// Causes the internal TString buffer to be deleted +#define MWF_DELETE 0x00000001 +/// Causes new buffer to be allocated with a specified size (empty one) +#define MWF_NEW 0x00000002 + +/** \brief Partial delete. + * + * If the object has to be allocated then it's done *without* allocating the internal buffer. + * Else the buffer is Left as is. + */ +#define MWF_PARTIALDEL 0x00000003 + +// structure containing all string data +namespace details { + +// class manages the internal contents of TString +class TInternalStringData +{ +private: + TInternalStringData(); + TInternalStringData(const TInternalStringData&); + ~TInternalStringData(); + +public: + // memory allocation/deallocation + static TInternalStringData* Allocate(size_t stBufferSize); + static void Free(TInternalStringData* pStringData); + + TInternalStringData* Clone(); + TInternalStringData* CloneWithResize(size_t stNewSize); + + TInternalStringData* CloneIfShared(bool& bCloned); + + // reference counting + void AddRef() { ++m_lRefCount; } + bool Release() { return (--m_lRefCount == 0); } + + // retrieving/setting data + static TInternalStringData* GetStringDataFromTextPointer(wchar_t* pszTextPointer) + { + if(pszTextPointer) + return (TInternalStringData*)((BYTE*)pszTextPointer - sizeof(TInternalStringData)); + else + return NULL; + } + + wchar_t* GetData() { return (wchar_t*)(((BYTE*)this) + sizeof(TInternalStringData)); } + size_t GetBufferSize() const { return m_stBufferSize; } + size_t GetStringLength() const { return m_stStringLength; } + + void SetStringLength(size_t stLength) + { + BOOST_ASSERT(stLength < m_stBufferSize); + m_stStringLength = min(stLength, m_stBufferSize - 1); + } + +private: + size_t m_stBufferSize; // allocated buffer size (only the string part - it excludes this structure; it is really the count of wchar_t's the buffer can contain) + long m_lRefCount; + size_t m_stStringLength; // string GetLength without terminating null +}; + +} // end of namespace details + +/////////////////////////////////////////////////////////////// +// TString manipulation class +/** \brief String manipulation class + * + * Class allows user to manipulate TString objects (either standard ANSI char_t* + * based strings or UNICODE ones - wchar_t related) with simple functions and + * operators. + */ +class LIBCHCORE_API TString +{ +public: + static size_t npos; + +public: +/** \name Construction/destruction */ +/*@{*/ + TString(); ///< Standard constructor + TString(const wchar_t* pszStr); ///< Constructor that takes const wchar_t* as an initial TString + TString(const wchar_t* pszStart, const wchar_t* pszEnd); + TString(const wchar_t* pszStart, size_t stCount); + TString(const TString& str); ///< Standard copy constructor + + ~TString(); ///< Standard destructor +/*@}*/ + +/** \name Operators */ +/**@{*/ + // assignment + const TString& operator=(const TString& src); ///< Assign operator for TString objects + const TString operator+(const TString& src) const; ///< Concatenate operator for TString objects + const TString& operator+=(const TString& src); ///< Merge operator for TString objects + + const TString& operator=(const wchar_t* pszSrc); ///< Assign operator from unicode strings + const TString operator+(const wchar_t* pszSrc) const; ///< Concatenate operator for unicode strings + const TString& operator+=(const wchar_t* pszSrc); ///< Merge operator for unicode strings + + /// Makes case sensitive comparison to the unicode TString ( see Compare(const wchar_t* psz) ) + bool operator<(const wchar_t* psz) const { return Compare(psz) < 0; }; + /// Makes case sensitive comparison to the unicode TString ( see Compare(const wchar_t* psz) ) + bool operator<=(const wchar_t* psz) const { return Compare(psz) <= 0; }; + /// Makes case sensitive comparison to the unicode TString ( see Compare(const wchar_t* psz) ) + bool operator==(const wchar_t* psz) const { return Compare(psz) == 0; }; + /// Makes case sensitive comparison to the unicode TString ( see Compare(const wchar_t* psz) ) + bool operator>=(const wchar_t* psz) const { return Compare(psz) >= 0; }; + /// Makes case sensitive comparison to the unicode TString ( see Compare(const wchar_t* psz) ) + bool operator>(const wchar_t* psz) const { return Compare(psz) > 0; }; + /// Makes case sensitive comparison to the unicode TString ( see Compare(const wchar_t* psz) ) + bool operator!=(const wchar_t* psz) const { return Compare(psz) != 0; }; + + /// Makes case sensitive comparison to the TString object ( see Compare(const TString& str) ) + bool operator<(const TString& str) const { return Compare(str) < 0; }; + /// Makes case sensitive comparison to the TString object ( see Compare(const TString& str) ) + bool operator<=(const TString& str) const { return Compare(str) <= 0; }; + /// Makes case sensitive comparison to the TString object ( see Compare(const TString& str) ) + bool operator==(const TString& str) const { return Compare(str) == 0; }; + /// Makes case sensitive comparison to the TString object ( see Compare(const TString& str) ) + bool operator>=(const TString& str) const { return Compare(str) >= 0; }; + /// Makes case sensitive comparison to the TString object ( see Compare(const TString& str) ) + bool operator>(const TString& str) const { return Compare(str) >= 0; }; + /// Makes case sensitive comparison to the TString object ( see Compare(const TString& str) ) + bool operator!=(const TString& str) const { return Compare(str) != 0; }; + + // cast operators + operator const wchar_t*() const; ///< Cast operator to wchar_t* +/**@}*/ + +/** \name Standard operations */ +/**@{*/ + // appends the given TString to this + void Append(const wchar_t* pszSrc); ///< Appends an unicode TString to the TString object + void Append(const TString& src); ///< Appends a TString object to another TString object + + TString Left(size_t tLen) const; ///< Returns TString with the Left part of a source TString + TString Right(size_t tLen) const; ///< Returns TString with the Right part of a source TString + TString Mid(size_t tStart, size_t tLen = (size_t)-1) const; ///< Returns TString with the middle part of a source TString + TString MidByPos(size_t tStart, size_t stAfterEndPos) const; ///< Returns TString with the middle part of a source TString + + void LeftSelf(size_t tLen); ///< Makes this TString it's Left part + void RightSelf(size_t tLen); ///< Makes this TString it's Right part + void MidSelf(size_t tStart, size_t tLen = (size_t)-1); ///< Makes this TString it's middle part + + void DeleteChar(size_t stIndex); + void Delete(size_t stIndex, size_t stCount); + + void Split(const wchar_t* pszSeparators, TStringArray& rStrings) const; + + // comparation + int_t Compare(const wchar_t* psz) const; ///< Comparison of this TString object with a given unicode TString + int_t Compare(const TString& str) const; ///< Comparison of this TString object with another TString object + + int_t CompareNoCase(const wchar_t* psz) const; ///< Comparison (case insensitive) of this TString object with a given unicode TString + int_t CompareNoCase(const TString& str) const; ///< Comparison (case insensitive) of this TString object with another TString object + + bool StartsWith(const wchar_t* pszText) const; + bool StartsWithNoCase(const wchar_t* pszText) const; + + bool EndsWith(const wchar_t* pszText) const; + bool EndsWithNoCase(const wchar_t* pszText) const; + + size_t FindFirstOf(const wchar_t* pszChars, size_t stStartFromPos = 0) const; + size_t FindLastOf(const wchar_t* pszChars) const; + + bool GetAt(size_t tPos, wchar_t& wch) const; ///< Gets a character at a specified position + wchar_t GetAt(size_t tPos) const; + + wchar_t* GetBuffer(size_t tMinSize); ///< Gives user access to the unicode internal buffer + void ReleaseBuffer(); ///< Releases the buffer get from get_bufferx functions + void ReleaseBufferSetLength(size_t tSize); + + size_t GetLength() const; ///< Returns the GetLength of this TString in chars + + void Clear(); ///< Clear the contents of the TString object + + bool IsEmpty() const; ///< Returns true if the TString is empty +/**@}*/ + + // Serialization + template + void load(Archive& ar, unsigned int /*uiVersion*/) + { + std::wstring wstrData; + ar & wstrData; + SetString(wstrData.c_str()); + } + + template + void save(Archive& ar, unsigned int /*uiVersion*/) const + { + std::wstring wstrData = m_pszStringData ? m_pszStringData : _T(""); + ar & wstrData; + } + + BOOST_SERIALIZATION_SPLIT_MEMBER(); + +protected: + void SetString(const wchar_t* pszStr); ///< Makes a copy of a given unicode TString and store it in internal TString buffer + void SetString(const wchar_t* pszStart, size_t stCount); + + void EnsureWritable(size_t stRequestedSize); + + void AddRef() + { + if(m_pszStringData) + { + details::TInternalStringData* pInternalStringData = details::TInternalStringData::GetStringDataFromTextPointer(m_pszStringData); + pInternalStringData->AddRef(); + } + } + + void Release() + { + details::TInternalStringData* pInternalStringData = details::TInternalStringData::GetStringDataFromTextPointer(m_pszStringData); + if(pInternalStringData && pInternalStringData->Release()) + details::TInternalStringData::Free(pInternalStringData); + m_pszStringData = NULL; + } + + size_t GetCurrentBufferSize() const + { + const details::TInternalStringData* pData = GetInternalStringData(); + if(pData) + return pData->GetBufferSize(); + else + return 0; + } + + details::TInternalStringData* GetInternalStringData() { return details::TInternalStringData::GetStringDataFromTextPointer(m_pszStringData); } + const details::TInternalStringData* GetInternalStringData() const { return details::TInternalStringData::GetStringDataFromTextPointer(m_pszStringData); } + +protected: + wchar_t* m_pszStringData; ///< Pointer to an underlying c string (with prepended TInternalStringData) +}; + +END_CHCORE_NAMESPACE + +LIBCHCORE_API chcore::TString operator+(const wchar_t* pszString, chcore::TString& str); + +#endif Index: src/libchcore/TStringArray.cpp =================================================================== diff -u -N --- src/libchcore/TStringArray.cpp (revision 0) +++ src/libchcore/TStringArray.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,132 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TStringArray.cpp +/// @date 2011/06/05 +/// @brief Contains implementation of string array. +// ============================================================================ +#include "stdafx.h" +#include "TStringArray.h" + +BEGIN_CHCORE_NAMESPACE + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// class TStringArrayIterator + +TStringArrayIterator::TStringArrayIterator(std::vector::iterator iterArray) : + m_iterArray(iterArray) +{ +} + +TStringArrayIterator::TStringArrayIterator() +{ +} + +TStringArrayIterator::~TStringArrayIterator() +{ +} + +TStringArrayIterator TStringArrayIterator::operator++(int) +{ + TStringArrayIterator iterCurrent = *this; + ++m_iterArray; + return iterCurrent; +} + +TStringArrayIterator& TStringArrayIterator::operator++() +{ + ++m_iterArray; + return *this; +} + +bool TStringArrayIterator::operator==(const TStringArrayIterator& rSrc) const +{ + return m_iterArray == rSrc.m_iterArray; +} + +bool TStringArrayIterator::operator!=(const TStringArrayIterator& rSrc) const +{ + return m_iterArray != rSrc.m_iterArray; +} + +TString& TStringArrayIterator::operator*() +{ + return *m_iterArray; +} + +const TString& TStringArrayIterator::operator*() const +{ + return *m_iterArray; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// class TStringArray +TStringArray::TStringArray() +{ +} + +TStringArray::~TStringArray() +{ +} + +void TStringArray::Add(const TString& str) +{ + m_vItems.push_back(str); +} + +void TStringArray::InsertAt(size_t stIndex, const TString& str) +{ + m_vItems.insert(m_vItems.begin() + stIndex, str); +} + +void TStringArray::SetAt(size_t stIndex, const TString& str) +{ + m_vItems[stIndex] = str; +} + +void TStringArray::RemoveAt(size_t stIndex) +{ + m_vItems.erase(m_vItems.begin() + stIndex); +} + +void TStringArray::Clear() +{ + m_vItems.clear(); +} + +const TString& TStringArray::GetAt(size_t stIndex) const +{ + return m_vItems.at(stIndex); +} + +size_t TStringArray::GetCount() const +{ + return m_vItems.size(); +} + +TStringArrayIterator TStringArray::Begin() +{ + return TStringArrayIterator(m_vItems.begin()); +} + +TStringArrayIterator TStringArray::End() +{ + return TStringArrayIterator(m_vItems.end()); +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TStringArray.h =================================================================== diff -u -N --- src/libchcore/TStringArray.h (revision 0) +++ src/libchcore/TStringArray.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,88 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TStringArray.h +/// @date 2011/06/05 +/// @brief Contains string array definition. +// ============================================================================ +#ifndef __TSTRINGARRAY_H__ +#define __TSTRINGARRAY_H__ + +#include "TString.h" +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +class LIBCHCORE_API TStringArrayIterator +{ +protected: + TStringArrayIterator(std::vector::iterator iterArray); + +public: + TStringArrayIterator(); + ~TStringArrayIterator(); + + TStringArrayIterator operator++(int); + TStringArrayIterator& operator++(); + + bool operator==(const TStringArrayIterator& rSrc) const; + bool operator!=(const TStringArrayIterator& rSrc) const; + + TString& operator*(); + const TString& operator*() const; + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::vector::iterator m_iterArray; +#pragma warning(pop) + + friend class TStringArray; +}; + +class LIBCHCORE_API TStringArray +{ +public: + typedef TStringArrayIterator iterator; + +public: + TStringArray(); + ~TStringArray(); + + void Add(const TString& str); + void InsertAt(size_t stIndex, const TString& str); + void SetAt(size_t stIndex, const TString& str); + void RemoveAt(size_t stIndex); + void Clear(); + + const TString& GetAt(size_t stIndex) const; + size_t GetCount() const; + + TStringArrayIterator Begin(); + TStringArrayIterator End(); + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::vector m_vItems; +#pragma warning(pop) +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TStringSet.cpp =================================================================== diff -u -N --- src/libchcore/TStringSet.cpp (revision 0) +++ src/libchcore/TStringSet.cpp (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,194 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TStringSet.cpp +/// @date 2011/06/05 +/// @brief Contains implementation of string set. +// ============================================================================ +#include "stdafx.h" +#include "TStringSet.h" + +BEGIN_CHCORE_NAMESPACE + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TStringSetIterator + +TStringSetIterator::TStringSetIterator(std::set::iterator iterSet) : + m_iterSet(iterSet) +{ +} + +TStringSetIterator::TStringSetIterator() +{ + +} + +TStringSetIterator::~TStringSetIterator() +{ + +} + +TStringSetIterator TStringSetIterator::operator++(int) +{ + TStringSetIterator iterCurrent(m_iterSet); + ++m_iterSet; + return iterCurrent; +} + +TStringSetIterator& TStringSetIterator::operator++() +{ + ++m_iterSet; + return *this; +} + +bool TStringSetIterator::operator==(const TStringSetIterator& rSrc) const +{ + return m_iterSet == rSrc.m_iterSet; +} + +bool TStringSetIterator::operator!=(const TStringSetIterator& rSrc) const +{ + return m_iterSet != rSrc.m_iterSet; +} + +TString& TStringSetIterator::operator*() +{ + return *m_iterSet; +} + +const TString& TStringSetIterator::operator*() const +{ + return *m_iterSet; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TStringSetConstIterator + +TStringSetConstIterator::TStringSetConstIterator(std::set::const_iterator iterSet) : + m_iterSet(iterSet) +{ +} + +TStringSetConstIterator::TStringSetConstIterator() +{ + +} + +TStringSetConstIterator::~TStringSetConstIterator() +{ + +} + +TStringSetConstIterator TStringSetConstIterator::operator++(int) +{ + TStringSetConstIterator iterCurrent(m_iterSet); + ++m_iterSet; + return iterCurrent; +} + +TStringSetConstIterator& TStringSetConstIterator::operator++() +{ + ++m_iterSet; + return *this; +} + +bool TStringSetConstIterator::operator==(const TStringSetConstIterator& rSrc) const +{ + return m_iterSet == rSrc.m_iterSet; +} + +bool TStringSetConstIterator::operator!=(const TStringSetConstIterator& rSrc) const +{ + return m_iterSet != rSrc.m_iterSet; +} + +const TString& TStringSetConstIterator::operator*() const +{ + return *m_iterSet; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// class TStringSet + +TStringSet::TStringSet() +{ +} + +TStringSet::~TStringSet() +{ +} + +void TStringSet::Insert(const TString& str) +{ + m_setItems.insert(str); +} + +void TStringSet::Insert(const TStringSet& setStrings) +{ + m_setItems.insert(setStrings.m_setItems.begin(), setStrings.m_setItems.end()); +} + +void TStringSet::Remove(const TString& str) +{ + std::set::iterator iter = m_setItems.find(str); + if(iter != m_setItems.end()) + m_setItems.erase(iter); +} + +void TStringSet::Clear() +{ + m_setItems.clear(); +} + +bool TStringSet::HasValue(const TString& str) const +{ + std::set::const_iterator iter = m_setItems.find(str); + return (iter != m_setItems.end()); +} + +size_t TStringSet::GetCount() const +{ + return m_setItems.size(); +} + +bool TStringSet::IsEmpty() const +{ + return m_setItems.empty(); +} + +TStringSetIterator TStringSet::Begin() +{ + return TStringSetIterator(m_setItems.begin()); +} + +TStringSetIterator TStringSet::End() +{ + return TStringSetIterator(m_setItems.end()); +} + +TStringSetConstIterator TStringSet::Begin() const +{ + return TStringSetConstIterator(m_setItems.begin()); +} + +TStringSetConstIterator TStringSet::End() const +{ + return TStringSetConstIterator(m_setItems.end()); +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TStringSet.h =================================================================== diff -u -N --- src/libchcore/TStringSet.h (revision 0) +++ src/libchcore/TStringSet.h (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -0,0 +1,117 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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 Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TStringSet.h +/// @date 2011/06/05 +/// @brief Contains definition of string set. +// ============================================================================ +#ifndef __TSTRINGSET_H__ +#define __TSTRINGSET_H__ + +#include "TString.h" +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +class LIBCHCORE_API TStringSetIterator +{ +protected: + TStringSetIterator(std::set::iterator iterSet); + +public: + TStringSetIterator(); + ~TStringSetIterator(); + + TStringSetIterator operator++(int); + TStringSetIterator& operator++(); + + bool operator==(const TStringSetIterator& rSrc) const; + bool operator!=(const TStringSetIterator& rSrc) const; + + TString& operator*(); + const TString& operator*() const; + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::set::iterator m_iterSet; +#pragma warning(pop) + + friend class TStringSet; +}; + +class LIBCHCORE_API TStringSetConstIterator +{ +protected: + TStringSetConstIterator(std::set::const_iterator iterSet); + +public: + TStringSetConstIterator(); + ~TStringSetConstIterator(); + + TStringSetConstIterator operator++(int); + TStringSetConstIterator& operator++(); + + bool operator==(const TStringSetConstIterator& rSrc) const; + bool operator!=(const TStringSetConstIterator& rSrc) const; + + const TString& operator*() const; + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::set::const_iterator m_iterSet; +#pragma warning(pop) + + friend class TStringSet; +}; + +class LIBCHCORE_API TStringSet +{ +public: + typedef TStringSetIterator iterator; + typedef TStringSetConstIterator const_iterator; + +public: + TStringSet(); + ~TStringSet(); + + void Insert(const TString& str); + void Insert(const TStringSet& setStrings); + void Remove(const TString& str); + void Clear(); + + bool HasValue(const TString& str) const; + size_t GetCount() const; + bool IsEmpty() const; + + TStringSetIterator Begin(); + TStringSetIterator End(); + TStringSetConstIterator Begin() const; + TStringSetConstIterator End() const; + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + std::set m_setItems; +#pragma warning(pop) +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TTaskDefinition.cpp =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -74,7 +74,7 @@ } // Task unique id -std::wstring TTaskDefinition::GetTaskUniqueID() const +TString TTaskDefinition::GetTaskUniqueID() const { return m_strTaskUniqueID; } @@ -168,7 +168,7 @@ tTaskInfo.Read(strPath.c_str()); // clear everything - m_strTaskUniqueID.clear(); + m_strTaskUniqueID.Clear(); m_vSourcePaths.Clear(); m_pathDestinationPath.Clear(); @@ -178,7 +178,7 @@ // get information from config file // task unique id - use if provided, generate otherwise - if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.UniqueID"), m_strTaskUniqueID) || m_strTaskUniqueID.empty()) + if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.UniqueID"), m_strTaskUniqueID) || m_strTaskUniqueID.IsEmpty()) { boost::uuids::random_generator gen; boost::uuids::uuid u = gen(); @@ -189,7 +189,7 @@ // basic information // source paths to be processed - if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.SourcePaths"), m_vSourcePaths) || m_vSourcePaths.IsEmpty()) + if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.SourcePaths.Path"), m_vSourcePaths) || m_vSourcePaths.IsEmpty()) THROW_CORE_EXCEPTION_STR(eMissingData, _T("Missing source paths")); // destination path @@ -283,7 +283,7 @@ tTaskInfo.ReadFromString(strInput); // clear everything - m_strTaskUniqueID.clear(); + m_strTaskUniqueID.Clear(); m_vSourcePaths.Clear(); m_pathDestinationPath.Clear(); @@ -293,7 +293,7 @@ // get information from config file // task unique id - use if provided, generate otherwise - if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.UniqueID"), m_strTaskUniqueID) || m_strTaskUniqueID.empty()) + if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.UniqueID"), m_strTaskUniqueID) || m_strTaskUniqueID.IsEmpty()) { boost::uuids::random_generator gen; boost::uuids::uuid u = gen(); @@ -304,7 +304,7 @@ // basic information // source paths to be processed - if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.SourcePaths"), m_vSourcePaths) || m_vSourcePaths.IsEmpty()) + if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.SourcePaths.Path"), m_vSourcePaths) || m_vSourcePaths.IsEmpty()) THROW_CORE_EXCEPTION_STR(eMissingData, _T("Missing source paths")); // destination path Index: src/libchcore/TTaskDefinition.h =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TTaskDefinition.h (.../TTaskDefinition.h) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/TTaskDefinition.h (.../TTaskDefinition.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -42,7 +42,7 @@ TTaskDefinition& operator=(const TTaskDefinition& rSrc); // Task unique ID - std::wstring GetTaskUniqueID() const; + TString GetTaskUniqueID() const; // Source paths void AddSourcePath(const chcore::TSmartPath& tPath); @@ -75,10 +75,7 @@ void LoadFromString(const TWStringData& strInput); private: -#pragma warning(push) -#pragma warning(disable: 4251) - std::wstring m_strTaskUniqueID; ///< Unique ID of the task that will process this request (generated automatically) -#pragma warning(pop) + TString m_strTaskUniqueID; ///< Unique ID of the task that will process this request (generated automatically) // basic information chcore::TPathContainer m_vSourcePaths; Index: src/libchcore/TTaskOperationPlan.h =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/TTaskOperationPlan.h (.../TTaskOperationPlan.h) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/TTaskOperationPlan.h (.../TTaskOperationPlan.h) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -25,20 +25,10 @@ #include "libchcore.h" #include +#include "EOperationTypes.h" BEGIN_CHCORE_NAMESPACE -// enum represents type of the operation handled by the task -enum EOperationType -{ - eOperation_None, - eOperation_Copy, - eOperation_Move, - - // add new operation types before this enum value - eOperation_Max -}; - enum ESubOperationType { eSubOperation_None, Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -N -r2d7bee54f998ae8f5d4145a2cf3f4a589253016f -r633a533cb6e741d44fe28aa56339e1d2709b1b27 --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 2d7bee54f998ae8f5d4145a2cf3f4a589253016f) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) @@ -436,6 +436,10 @@ > + + @@ -472,6 +476,38 @@ > + + + + + + + + + + + + + + + +