This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / system / explorer / Seashell / SeaShellExt / cbformats.cpp
diff --git a/subsys/system/explorer/Seashell/SeaShellExt/cbformats.cpp b/subsys/system/explorer/Seashell/SeaShellExt/cbformats.cpp
new file mode 100644 (file)
index 0000000..1e1a2e7
--- /dev/null
@@ -0,0 +1,667 @@
+//*******************************************************************************
+// COPYRIGHT NOTES
+// ---------------
+// You may use this source code, compile or redistribute it as part of your application 
+// for free. You cannot redistribute it as a part of a software development 
+// library without the agreement of the author. If the sources are 
+// distributed along with the application, you should leave the original 
+// copyright notes in the source code without any changes.
+// This code can be used WITHOUT ANY WARRANTIES at your own risk.
+// 
+// For the latest updates to this code, check this site:
+// http://www.masmex.com 
+// after Sept 2000
+// 
+// Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
+//*******************************************************************************
+
+#include "stdafx.h"
+#include "cbformats.h"
+#include "shlobj.h"
+#include "ShellPidl.h"
+#include <afxpriv.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//static
+CWDClipboardData *CWDClipboardData::Instance()
+{
+       static CWDClipboardData data;
+       return &data;
+}
+
+CWDClipboardData::CWDClipboardData()
+{
+       m_aFormatIDs[e_cfString] = CF_TEXT;
+       m_aFormatIDs[e_cfHDROP] = CF_HDROP;
+       m_aFormatIDs[e_cfWebSiteURL] = ::RegisterClipboardFormat(CFSTR_SHELLURL);
+#ifdef _UNICODE
+       m_aFormatIDs[e_cfFileGroupDesc] = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
+#else
+       m_aFormatIDs[e_cfFileGroupDesc] = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA);
+#endif
+       m_aFormatIDs[e_cfHTMLFormat] = ::RegisterClipboardFormat(_T("HTML Format"));
+       m_aFormatIDs[e_cfWebSite] = ::RegisterClipboardFormat(_T("CF_WD_WEBSITE"));
+       m_aFormatIDs[e_cfRightMenu] = ::RegisterClipboardFormat(_T("CF_WD_RIGHTMENU"));
+       m_aFormatIDs[e_cfFolder] = ::RegisterClipboardFormat(_T("CF_WD_WEBSITE_CATEGORY"));
+       m_aFormatIDs[e_cfShellIDList] = ::RegisterClipboardFormat(CFSTR_SHELLIDLIST);
+}
+
+CWDClipboardData::~CWDClipboardData()
+{
+}
+
+bool CWDClipboardData::IsValidFormat(CLIPFORMAT cfFormat)
+{
+       for(int i=0;i < e_cfMax;i++)
+       {
+               if (m_aFormatIDs[i] == cfFormat)
+                       break;
+       }
+       return(i != e_cfMax);
+}
+
+bool CWDClipboardData::IsDataAvailable(COleDataObject *pDataObject)
+{
+       // Iterate through the clipboard formats
+       pDataObject->BeginEnumFormats();
+       FORMATETC FormatEtc;
+       bool bFound=false;
+#ifdef _DEBUG
+       TCHAR szBuf[128];
+#endif
+       while (pDataObject->GetNextFormat(&FormatEtc))
+       {
+#ifdef _DEBUG
+               szBuf[0] = 0;
+               if (FormatEtc.cfFormat > CF_MAX)
+               {
+                       ::GetClipboardFormatName(FormatEtc.cfFormat,szBuf,sizeof(szBuf)-1);
+               }
+               else
+               {
+                       lstrcpy(szBuf,_T("Predefined Format"));
+               }
+               TRACE(_T("Enum formats returned %u(%s) %d\n"),FormatEtc.cfFormat,szBuf,FormatEtc.tymed);
+#endif
+               if (IsValidFormat(FormatEtc.cfFormat))
+               {
+#ifdef _DEBUG
+                       TRACE(_T("Clipboard format found %u(%s) tymed(%d), Aspect(%d)\n"),FormatEtc.cfFormat,szBuf,FormatEtc.tymed,FormatEtc.dwAspect);
+#endif
+                       bFound=true;
+               }
+       }       
+       return bFound;
+}
+
+CLIPFORMAT CWDClipboardData::GetClipboardFormat(eCBFormats format)
+{
+       return m_aFormatIDs[format]; 
+}
+
+void CWDClipboardData::SetData(COleDataSource *pOleDataSource,CObject *pObj,eCBFormats format,LPFORMATETC lpFormatEtc)
+{
+       ASSERT(pOleDataSource);
+       ASSERT(pObj);
+
+       // use serialization
+       CSharedFile file;
+       CArchive ar(&file,CArchive::store);
+       pObj->Serialize(ar);
+       ar.Close();
+
+       // cache into drag drop source
+       pOleDataSource->CacheGlobalData(CWDClipboardData::Instance()->GetClipboardFormat(format),file.Detach(),lpFormatEtc);            
+}
+
+bool CWDClipboardData::GetData(COleDataObject *pDataObject,CObject *pObj,eCBFormats format)
+{
+       ASSERT(pDataObject);
+       ASSERT(pObj);
+       if (pDataObject == NULL || pObj == NULL)
+               return false;
+
+       if (m_aFormatIDs[format] == CF_HDROP)
+       {
+               FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+               STGMEDIUM medium;
+               if (pDataObject->GetData(CF_HDROP, &medium, &fmte))
+               {
+                       HDROP hDropInfo = (HDROP)medium.hGlobal;
+                       UINT wNumFilesDropped = DragQueryFile(hDropInfo, 0XFFFFFFFF, NULL, 0);
+                       TCHAR szFile[MAX_PATH];
+                       ASSERT_KINDOF(CCF_HDROP,pObj);
+                       CCF_HDROP *pHDROP = (CCF_HDROP*)pObj;
+                       UINT nLen;
+                       for(UINT i=0; i < wNumFilesDropped;i++)
+                       {
+                               nLen = DragQueryFile(hDropInfo,i,szFile,sizeof(szFile)/sizeof(TCHAR));
+                               if (nLen)
+                               {
+                                       pHDROP->AddFileName(szFile);
+                               }
+                       }
+                       if (medium.pUnkForRelease)
+                               medium.pUnkForRelease->Release();
+                       else
+                               GlobalFree(medium.hGlobal);
+               }
+       }
+       else
+       {
+               CFile *pFile = pDataObject->GetFileData(CWDClipboardData::Instance()->GetClipboardFormat(format));
+               if (pFile)
+               {
+                       CArchive ar(pFile,CArchive::load);
+                       pObj->Serialize(ar);
+                       ar.Close();
+                       delete pFile;
+               }
+       }
+       return true;
+}
+
+///////////////////////////////////////////
+//
+//     Clipboard objects
+//
+///////////////////////////////////////////
+IMPLEMENT_SERIAL(CCF_App, CObject, 0 );
+IMPLEMENT_SERIAL(CCF_WebSites,CObject,0);
+IMPLEMENT_SERIAL(CCF_String, CObject, 0 );
+IMPLEMENT_SERIAL(CCF_WebSite, CObject, 0 );
+IMPLEMENT_SERIAL(CCF_FolderType, CObject, 0 );
+IMPLEMENT_SERIAL(CCF_DBFolderList,CObject,0);
+IMPLEMENT_SERIAL(CCF_RightMenu, CObject, 0 );
+IMPLEMENT_SERIAL(CCF_FileGroupDescriptor,CObject,0);
+IMPLEMENT_SERIAL(CCF_ShellIDList,CObject,0);
+IMPLEMENT_SERIAL(CCF_HDROP,CObject,0);
+///////////////////////////////////////////
+bool CCF_RightMenu::IsRightDrag()
+{
+       return m_bRightDrag;
+}
+
+void CCF_RightMenu::SetRightDrag(bool bRightDrag)
+{
+       m_bRightDrag = bRightDrag;
+}
+
+void CCF_RightMenu::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               int nRightDrag;
+               ar >> nRightDrag;
+               m_bRightDrag = nRightDrag == 1;
+       }
+       else
+       {
+               ar << m_bRightDrag;
+       }
+}
+
+CCF_FileGroupDescriptor::CCF_FileGroupDescriptor() 
+{
+       m_pFileDescrs = NULL;
+       m_nItems = 0;
+}
+
+CCF_FileGroupDescriptor::~CCF_FileGroupDescriptor()
+{
+       delete []m_pFileDescrs;
+}
+
+LPFILEDESCRIPTOR CCF_FileGroupDescriptor::GetFileDescriptor(UINT nItem)
+{
+       if (m_pFileDescrs == NULL)
+               return NULL;
+       if (nItem >= m_nItems)
+       {
+               ASSERT(FALSE);
+               return NULL;
+       }
+       return &m_pFileDescrs[nItem];
+}
+
+void CCF_FileGroupDescriptor::SetTitle(const CString &sTitle)
+{
+       m_sTitle = sTitle;
+}
+
+CString CCF_FileGroupDescriptor::GetFileName(UINT nItem)
+{
+       if (nItem >= m_nItems || m_pFileDescrs == NULL)
+       {
+               ASSERT(FALSE);
+               return CString();
+       }
+       return m_pFileDescrs[nItem].cFileName;
+}
+
+CString CCF_FileGroupDescriptor::GetTitle(UINT nItem)
+{
+       if (nItem >= m_nItems || m_pFileDescrs == NULL)
+       {
+               ASSERT(FALSE);
+               return CString();
+       }
+       CString strLink(m_pFileDescrs[nItem].cFileName);
+       int nPos = strLink.Find(_T(".URL"));
+       if (nPos < 0)
+               nPos = strLink.Find(_T(".url"));
+       if (nPos > 0)
+       {
+               return strLink.Left(nPos);
+       }
+       return strLink;
+}
+
+void CCF_FileGroupDescriptor::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               ar.Read(&m_nItems,sizeof(UINT));
+               if (m_nItems)
+               {
+                       m_pFileDescrs = new FILEDESCRIPTOR[m_nItems];
+                       ar.Read(m_pFileDescrs,sizeof(FILEDESCRIPTOR)*m_nItems);
+                       for(UINT i=0;i < m_nItems;i++)
+                               TRACE3("(%u) - cFileName %s, Size=%u\n",i,m_pFileDescrs[i].cFileName,m_pFileDescrs[i].nFileSizeLow);
+               }
+       }
+       else
+       {
+               UINT cItems=1;
+               ar.Write(&cItems,sizeof(UINT));
+               FILEDESCRIPTOR FileDesc;
+               ZeroMemory(&FileDesc,sizeof(FILEDESCRIPTOR));
+               FileDesc.dwFlags = (FD_LINKUI | FD_FILESIZE);
+               if (!m_sTitle.IsEmpty())
+               {
+                       lstrcpy(FileDesc.cFileName,m_sTitle);
+                       lstrcat(FileDesc.cFileName,_T(".url"));
+                       FileDesc.nFileSizeLow = lstrlen(FileDesc.cFileName)+24;
+                       ar.Write(&FileDesc,sizeof(FILEDESCRIPTOR));
+               }
+       }
+}
+
+////////////////////////////////////////////////
+// CCF_HDROP
+////////////////////////////////////////////////
+CCF_HDROP::CCF_HDROP() 
+{
+       m_nFiles = 0;
+       m_fNC = FALSE;
+}
+
+CCF_HDROP::~CCF_HDROP()
+{
+}
+
+CString CCF_HDROP::GetFileName(UINT nItem)
+{
+       if (m_sFileNames.GetSize() > 0)
+               return m_sFileNames[nItem];
+       return _T("");
+}
+
+void CCF_HDROP::AddDropPoint(CPoint &pt,BOOL fNC)
+{
+       m_pt = pt;
+       m_fNC = fNC;
+}
+
+void CCF_HDROP::AddFileName(LPCTSTR pszFileName)
+{
+       m_sFileNames.SetAtGrow(m_nFiles++,pszFileName);
+}
+
+void CCF_HDROP::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               // handled in GetData
+       }
+       else
+       {
+               DROPFILES dropfiles;
+               dropfiles.pFiles = sizeof(dropfiles);
+               dropfiles.fNC = m_fNC;
+               dropfiles.pt = m_pt;
+#ifdef _UNICODE
+               dropfiles.fWide = TRUE;
+#else
+               dropfiles.fWide = FALSE;
+#endif
+               ar.Write(&dropfiles,sizeof(DROPFILES));
+               LPCTSTR pszFileName=NULL;
+               for(int i=0; i < m_nFiles;i++)
+               {
+                       pszFileName=m_sFileNames[i];
+                       ar.Write(pszFileName,lstrlen(pszFileName)+sizeof(TCHAR));
+               }
+               TCHAR rchar=0;
+               ar.Write(&rchar,sizeof(TCHAR));
+       }
+}
+
+////////////////////////////////////////////////
+// CCF_ShellIDList
+////////////////////////////////////////////////
+CCF_ShellIDList::CCF_ShellIDList() 
+{
+}
+
+CCF_ShellIDList::~CCF_ShellIDList()
+{
+}
+
+LPCITEMIDLIST CCF_ShellIDList::operator[](UINT nIndex) const
+{
+       return GetPidl(nIndex);
+}
+
+LPCITEMIDLIST CCF_ShellIDList::GetPidl(UINT nIndex) const
+{
+       if (nIndex > (UINT)m_pidls.GetSize()) 
+       { 
+               return NULL; 
+       } 
+       return(m_pidls[nIndex]); 
+}
+
+UINT CCF_ShellIDList::GetCount() const
+{
+       return m_pidls.GetSize();  
+}
+
+void CCF_ShellIDList::AddPidl(LPCITEMIDLIST pidl)
+{
+       m_pidls.Add(pidl);
+}
+
+void CCF_ShellIDList::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               // read the header
+               CIDA cida;
+               ar.Read(&cida,sizeof(CIDA));
+               LPCITEMIDLIST pidl=NULL;
+               UINT nOffset;
+               // read the ITEMIDLIST structures
+               for(UINT i=0;i < cida.cidl+1;i++)
+               {
+                       nOffset = cida.aoffset[i];
+                       ar.GetFile()->Seek(CFile::begin,nOffset*sizeof(UINT));
+                       ar.Read((void*)pidl,sizeof(ITEMIDLIST));
+                       m_pidls.Add(pidl);
+               }
+       }
+       else
+       {
+               CShellPidl ShellPidl;
+               CIDA cida;
+               cida.cidl = m_pidls.GetSize();
+               ASSERT(cida.cidl > 1);
+               if (cida.cidl <= 1)
+                       return;
+               UINT pidls=cida.cidl-1;
+               ar.Write(&pidls,sizeof(pidls));
+               const UINT nOffset=sizeof(UINT);
+               UINT nElemOffset;
+               UINT nPidlSize=0;
+               for(UINT i1=0;i1 < cida.cidl;i1++)
+               {
+                       nElemOffset = sizeof(cida.cidl)+(cida.cidl*sizeof(nElemOffset))+nOffset+nPidlSize;
+                       ar.Write(&nElemOffset,sizeof(nElemOffset));
+                       nPidlSize += ShellPidl.GetSize(m_pidls[i1]);
+               }
+               BYTE nZero=0;
+               for(int i=0;i < nOffset;i++)
+                       ar.Write(&nZero,sizeof(nZero));
+               TRACE1("Writing %u pidls\n",cida.cidl);
+               LPSHELLFOLDER pFolder=ShellPidl.GetFolder((LPITEMIDLIST)m_pidls[0]);
+               for(UINT i2=0;i2 < cida.cidl;i2++)
+               {
+#ifdef _DEBUG
+                       CString sPath;
+                       ShellPidl.SHPidlToPathEx((LPITEMIDLIST)m_pidls[i2],sPath,pFolder);
+                       TRACE3("Writing pidl %s (%u) size(%u)\n",sPath,i2,ShellPidl.GetSize(m_pidls[i2]));
+#endif 
+                       ar.Write(m_pidls[i2],ShellPidl.GetSize(m_pidls[i2]));
+               }
+               if (pFolder)
+                       pFolder->Release();
+       }
+}
+
+///////////////////////////////////////////////////////////////////
+// Private clipboard formats for drag and drop
+///////////////////////////////////////////////////////////////////
+const CCF_WebSite &CCF_WebSite::operator=(const CCF_WebSite &rThat)
+{
+       if (this != &rThat)
+       {
+               m_strURL = rThat.m_strURL;
+               m_strTitle = rThat.m_strTitle;
+       }
+       return *this;
+}
+
+CCF_WebSite::CCF_WebSite(const CCF_WebSite &WebSite)
+{
+       *this = WebSite;
+}
+
+////////////////////////////////////////////
+
+void CCF_App::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               long hWnd;
+               ar >> hWnd;
+               m_hWnd = (HWND)hWnd;
+       }
+       else
+       {
+               ar << (long)m_hWnd;
+       }
+}
+/////////////////////////////////////////
+
+void CCF_WebSites::Serialize(CArchive &ar)
+{
+       m_App.Serialize(ar);
+       m_listWebSites.Serialize(ar);
+}
+
+/////////////////////////////////////////
+
+CCF_String::CCF_String(LPCTSTR pszText) : m_sText(pszText) 
+{
+}
+
+CCF_String::~CCF_String()
+{
+}
+
+LPCTSTR CCF_String::GetString()
+{
+       return m_sText;
+}
+
+void CCF_String::SetString(LPCTSTR pszText)
+{
+       m_sText = pszText;
+}
+
+void CCF_String::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               TCHAR szText[MAX_PATH+1];
+               m_sText.Empty();
+               while (1)
+               {
+                       ZeroMemory(szText,sizeof(szText));
+                       ar.Read(szText,MAX_PATH);
+                       m_sText += szText;
+                       if (lstrlen(szText) < MAX_PATH)
+                               break;
+               }
+       }
+       else
+       {
+               ar.Write((LPCTSTR)m_sText, m_sText.GetLength()*sizeof(TCHAR));
+               int null=0;
+               ar.Write(&null,sizeof(null));
+       }
+}
+
+//
+// Private clipboard formats for drag and drop
+//
+CCF_WebSite::CCF_WebSite(LPCTSTR pszURL,LPCTSTR pszTitle) : 
+       m_strURL(pszURL),
+               m_strTitle(pszTitle)
+{
+}
+
+CCF_WebSite::~CCF_WebSite()
+{
+}
+
+void CCF_WebSite::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               ar >> m_strURL;
+               ar >> m_strTitle;
+       }
+       else
+       {
+               ar << m_strURL;
+               ar << m_strTitle;
+       }
+}
+
+//
+//////////////////////////////////////////////////////
+
+CCF_FolderType::CCF_FolderType(LPCTSTR pszParentCategory,long nCategory,LPCTSTR pszCategory) :
+               m_strParentCategory(pszParentCategory),
+               m_nCategory(nCategory),
+               m_strCategory(pszCategory)
+{
+}
+
+CCF_FolderType::~CCF_FolderType()
+{
+}
+
+const CCF_FolderType &CCF_FolderType::operator=(const CCF_FolderType &rThat)
+{
+       if (this != &rThat)
+       {
+               m_nCategory = rThat.m_nCategory;
+               m_strCategory = rThat.m_strCategory;
+               m_strParentCategory = rThat.m_strParentCategory;
+       }
+       return *this;
+}
+
+CCF_FolderType::CCF_FolderType(const CCF_FolderType &WebSiteCategory)
+{
+       *this = WebSiteCategory;
+}
+
+void CCF_FolderType::Serialize(CArchive &ar)
+{
+       if (ar.IsLoading())
+       {
+               ar >> m_nCategory;
+               ar >> m_strCategory;
+               ar >> m_strParentCategory;
+       }
+       else
+       {
+               ar << m_nCategory;
+               ar << m_strCategory;
+               ar << m_strParentCategory;
+       }
+}
+
+/////////////////////////////////////////////////
+
+void CCF_DBFolderList::Serialize(CArchive &ar)
+{
+       m_App.Serialize(ar);
+       if (ar.IsLoading())
+       {
+               ar >> m_strDatabase;
+       }
+       else
+       {
+               ar << m_strDatabase;
+       }
+       CList<CCF_FolderType,CCF_FolderType&>::Serialize(ar);
+}
+
+template <> void AFXAPI SerializeElements <CCF_FolderType>(CArchive& ar, CCF_FolderType *pWebSite, int nCount )
+{
+    for ( int i = 0; i < nCount; i++, pWebSite++ )
+    {
+               pWebSite->Serialize(ar);
+       }
+}
+
+template<> void AFXAPI DestructElements<CCF_FolderType> (CCF_FolderType *pElements, int nCount)
+{
+       for ( int n = 0; n < nCount; n++, pElements++ )
+       {
+               pElements->CCF_FolderType::~CCF_FolderType();
+       }
+}
+
+template<> void AFXAPI ConstructElements<CCF_FolderType> (CCF_FolderType *pElements, int nCount)
+{
+       for ( int n = 0; n < nCount; n++, pElements++ )
+       {
+               pElements->CCF_FolderType::CCF_FolderType();
+       }
+}
+
+///////////////////////////////////////////////////    
+template <> void AFXAPI SerializeElements <CCF_WebSite>(CArchive& ar, CCF_WebSite *pWebSite, int nCount )
+{
+    for ( int i = 0; i < nCount; i++, pWebSite++ )
+    {
+               pWebSite->Serialize(ar);
+       }
+}
+
+template<> void AFXAPI DestructElements<CCF_WebSite> (CCF_WebSite *pElements, int nCount)
+{
+       for ( int n = 0; n < nCount; n++, pElements++ )
+       {
+               pElements->CCF_WebSite::~CCF_WebSite();
+       }
+}
+
+template<> void AFXAPI ConstructElements<CCF_WebSite> (CCF_WebSite *pElements, int nCount)
+{
+       for ( int n = 0; n < nCount; n++, pElements++ )
+       {
+               pElements->CCF_WebSite::CCF_WebSite();
+       }
+}
+