Back to index

lightning-sunbird  0.9+nobinonly
DropTarget.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Adam Lock <adamlock@eircom.net>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "stdafx.h"
00040 
00041 #include <intshcut.h>
00042 #include <shlobj.h>
00043 
00044 #include "DropTarget.h"
00045 
00046 #ifndef CFSTR_SHELLURL
00047 #define CFSTR_SHELLURL _T("UniformResourceLocator")
00048 #endif
00049 
00050 #ifndef CFSTR_FILENAME
00051 #define CFSTR_FILENAME _T("FileName")
00052 #endif
00053 
00054 #ifndef CFSTR_FILENAMEW
00055 #define CFSTR_FILENAMEW _T("FileNameW")
00056 #endif
00057 
00058 static const UINT g_cfURL = RegisterClipboardFormat(CFSTR_SHELLURL);
00059 static const UINT g_cfFileName = RegisterClipboardFormat(CFSTR_FILENAME);
00060 static const UINT g_cfFileNameW = RegisterClipboardFormat(CFSTR_FILENAMEW);
00061 
00062 CDropTarget::CDropTarget()
00063 {
00064     m_pOwner = NULL;
00065 }
00066 
00067 
00068 CDropTarget::~CDropTarget()
00069 {
00070 }
00071 
00072 
00073 void CDropTarget::SetOwner(CMozillaBrowser *pOwner)
00074 {
00075     m_pOwner = pOwner;
00076 }
00077 
00078 
00079 HRESULT CDropTarget::GetURLFromFile(const TCHAR *pszFile, tstring &szURL)
00080 {
00081     USES_CONVERSION;
00082     CIPtr(IUniformResourceLocator) spUrl;
00083 
00084     // Let's see if the file is an Internet Shortcut...
00085     HRESULT hr = CoCreateInstance (CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (void **) &spUrl);
00086     if (spUrl == NULL)
00087     {
00088         return E_FAIL;
00089     }
00090 
00091     // Get the IPersistFile interface
00092     CIPtr(IPersistFile) spFile = spUrl;
00093     if (spFile == NULL)
00094     {
00095         return E_FAIL;
00096     }
00097 
00098     // Initialise the URL object from the filename
00099     LPSTR lpTemp = NULL;
00100     if (FAILED(spFile->Load(T2OLE(pszFile), STGM_READ)) ||
00101         FAILED(spUrl->GetURL(&lpTemp)))
00102     {
00103         return E_FAIL;
00104     }
00105 
00106     // Free the memory
00107     CIPtr(IMalloc) spMalloc;
00108     if (FAILED(SHGetMalloc(&spMalloc)))
00109     {
00110         return E_FAIL;
00111     }
00112     
00113     // Copy the URL & cleanup
00114     szURL = A2T(lpTemp);
00115     spMalloc->Free(lpTemp);
00116 
00117     return S_OK;
00118 }
00119 
00121 // IDropTarget implementation
00122 
00123 HRESULT STDMETHODCALLTYPE CDropTarget::DragEnter(/* [unique][in] */ IDataObject __RPC_FAR *pDataObj, /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt, /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
00124 {
00125     if (pdwEffect == NULL || pDataObj == NULL)
00126     {
00127         NG_ASSERT(0);
00128         return E_INVALIDARG;
00129     }
00130 
00131     if (m_spDataObject != NULL)
00132     {
00133         NG_ASSERT(0);
00134         return E_UNEXPECTED;
00135     }
00136 
00137     // TODO process Internet Shortcuts (*.URL) files
00138     FORMATETC formatetc;
00139     memset(&formatetc, 0, sizeof(formatetc));
00140     formatetc.dwAspect = DVASPECT_CONTENT;
00141     formatetc.lindex = -1;
00142     formatetc.tymed = TYMED_HGLOBAL;
00143 
00144     // Test if the data object contains a text URL format
00145     formatetc.cfFormat = g_cfURL;
00146     if (pDataObj->QueryGetData(&formatetc) == S_OK)
00147     {
00148         m_spDataObject = pDataObj;
00149         *pdwEffect = DROPEFFECT_LINK;
00150         return S_OK;
00151     }
00152 
00153     // Test if the data object contains a file name
00154     formatetc.cfFormat = g_cfFileName;
00155     if (pDataObj->QueryGetData(&formatetc) == S_OK)
00156     {
00157         m_spDataObject = pDataObj;
00158         *pdwEffect = DROPEFFECT_LINK;
00159         return S_OK;
00160     }
00161     
00162     // Test if the data object contains a wide character file name
00163     formatetc.cfFormat = g_cfFileName;
00164     if (pDataObj->QueryGetData(&formatetc) == S_OK)
00165     {
00166         m_spDataObject = pDataObj;
00167         *pdwEffect = DROPEFFECT_LINK;
00168         return S_OK;
00169     }
00170 
00171     // If we got here, then the format is not supported
00172     *pdwEffect = DROPEFFECT_NONE;
00173     return S_OK;
00174 }
00175 
00176 
00177 HRESULT STDMETHODCALLTYPE CDropTarget::DragOver(/* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt, /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
00178 {
00179     if (pdwEffect == NULL)
00180     {
00181         NG_ASSERT(0);
00182         return E_INVALIDARG;
00183     }
00184     *pdwEffect = m_spDataObject ? DROPEFFECT_LINK : DROPEFFECT_NONE;
00185     return S_OK;
00186 }
00187 
00188 
00189 HRESULT STDMETHODCALLTYPE CDropTarget::DragLeave(void)
00190 {
00191     if (m_spDataObject)
00192     {
00193         m_spDataObject.Release();
00194     }
00195     return S_OK;
00196 }
00197 
00198 
00199 HRESULT STDMETHODCALLTYPE CDropTarget::Drop(/* [unique][in] */ IDataObject __RPC_FAR *pDataObj, /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt, /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
00200 {
00201     if (pdwEffect == NULL)
00202     {
00203         NG_ASSERT(0);
00204         return E_INVALIDARG;
00205     }
00206     if (m_spDataObject == NULL)
00207     {
00208         *pdwEffect = DROPEFFECT_NONE;
00209         return S_OK;
00210     }
00211 
00212     *pdwEffect = DROPEFFECT_LINK;
00213 
00214     // Get the URL from the data object
00215     BSTR bstrURL = NULL;
00216     FORMATETC formatetc;
00217     STGMEDIUM stgmedium;
00218     memset(&formatetc, 0, sizeof(formatetc));
00219     memset(&stgmedium, 0, sizeof(formatetc));
00220 
00221     formatetc.dwAspect = DVASPECT_CONTENT;
00222     formatetc.lindex = -1;
00223     formatetc.tymed = TYMED_HGLOBAL;
00224 
00225     // Does the data object contain a URL?
00226     formatetc.cfFormat = g_cfURL;
00227     if (m_spDataObject->GetData(&formatetc, &stgmedium) == S_OK)
00228     {
00229         NG_ASSERT(stgmedium.tymed == TYMED_HGLOBAL);
00230         NG_ASSERT(stgmedium.hGlobal);
00231         char *pszURL = (char *) GlobalLock(stgmedium.hGlobal);
00232         NG_TRACE("URL \"%s\" dragged over control\n", pszURL);
00233         // Browse to the URL
00234         if (m_pOwner)
00235         {
00236             USES_CONVERSION;
00237             bstrURL = SysAllocString(A2OLE(pszURL));
00238         }
00239         GlobalUnlock(stgmedium.hGlobal);
00240         goto finish;
00241     }
00242 
00243     // Does the data object point to a file?
00244     formatetc.cfFormat = g_cfFileName;
00245     if (m_spDataObject->GetData(&formatetc, &stgmedium) == S_OK)
00246     {
00247         USES_CONVERSION;
00248         NG_ASSERT(stgmedium.tymed == TYMED_HGLOBAL);
00249         NG_ASSERT(stgmedium.hGlobal);
00250         tstring szURL;
00251         char *pszURLFile = (char *) GlobalLock(stgmedium.hGlobal);
00252         NG_TRACE("File \"%s\" dragged over control\n", pszURLFile);
00253         if (SUCCEEDED(GetURLFromFile(A2T(pszURLFile), szURL)))
00254         {
00255             bstrURL = SysAllocString(T2OLE(szURL.c_str()));
00256         }
00257         GlobalUnlock(stgmedium.hGlobal);
00258         goto finish;
00259     }
00260     
00261     // Does the data object point to a wide character file?
00262     formatetc.cfFormat = g_cfFileNameW;
00263     if (m_spDataObject->GetData(&formatetc, &stgmedium) == S_OK)
00264     {
00265         USES_CONVERSION;
00266         NG_ASSERT(stgmedium.tymed == TYMED_HGLOBAL);
00267         NG_ASSERT(stgmedium.hGlobal);
00268         tstring szURL;
00269         WCHAR *pszURLFile = (WCHAR *) GlobalLock(stgmedium.hGlobal);
00270         NG_TRACE("File \"%s\" dragged over control\n", W2A(pszURLFile));
00271         if (SUCCEEDED(GetURLFromFile(W2T(pszURLFile), szURL)))
00272         {
00273             USES_CONVERSION;
00274             bstrURL = SysAllocString(T2OLE(szURL.c_str()));
00275         }
00276         GlobalUnlock(stgmedium.hGlobal);
00277         goto finish;
00278     }
00279 
00280 finish:
00281     // If we got a URL, browse there!
00282     if (bstrURL)
00283     {
00284         m_pOwner->Navigate(bstrURL, NULL, NULL, NULL, NULL);
00285         SysFreeString(bstrURL);
00286     }
00287 
00288     ReleaseStgMedium(&stgmedium);
00289     m_spDataObject.Release();
00290 
00291     return S_OK;
00292 }
00293