📄 droptarget.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//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 General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "emuledlg.h"
#include "DropTarget.h"
#include <intshcut.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define FILETYPE_INETSHRTCUT _T("Internet Shortcut File")
#define FILEEXT_INETSHRTCUTA "url" // ANSI string
#define FILEEXT_INETSHRTCUTW L"url" // UNICODE string
#define FILEEXT_INETSHRTCUT _T(FILEEXT_INETSHRTCUTA)
#define FILEEXTDOT_INETSHRTCUTA "." FILEEXT_INETSHRTCUTA // ANSI string
#define FILEEXTDOT_INETSHRTCUTW L"." FILEEXT_INETSHRTCUTW // UNICODE string
#define FILEEXTDOT_INETSHRTCUT _T(".") FILEEXT_INETSHRTCUT
#define FILEFLT_INETSHRTCUT FILETYPE_INETSHRTCUT _T("s (*") FILEEXTDOT_INETSHRTCUT _T(")|*") FILEEXTDOT_INETSHRTCUT _T("|")
BOOL IsUrlSchemeSupportedA(LPCSTR pszUrl)
{
static const struct SCHEME
{
LPCSTR pszPrefix;
int iLen;
} _aSchemes[] =
{
#define SCHEME_ENTRY(prefix) { prefix, ARRSIZE(prefix)-1 }
SCHEME_ENTRY("ed2k://")
#undef SCHEME_ENTRY
};
for (int i = 0; i < ARRSIZE(_aSchemes); i++)
{
if (strncmp(pszUrl, _aSchemes[i].pszPrefix, _aSchemes[i].iLen) == 0)
return TRUE;
}
return FALSE;
}
BOOL IsUrlSchemeSupportedW(LPCWSTR pszUrl)
{
static const struct SCHEME
{
LPCWSTR pszPrefix;
int iLen;
} _aSchemes[] =
{
#define SCHEME_ENTRY(prefix) { prefix, ARRSIZE(prefix)-1 }
SCHEME_ENTRY(L"ed2k://")
#undef SCHEME_ENTRY
};
for (int i = 0; i < ARRSIZE(_aSchemes); i++)
{
if (wcsncmp(pszUrl, _aSchemes[i].pszPrefix, _aSchemes[i].iLen) == 0)
return TRUE;
}
return FALSE;
}
// GetFileExtA -- ANSI version
//
// This function is thought to be used only for filenames which have been
// validated by 'GetFullPathName' or similar functions.
LPCSTR GetFileExtA(LPCSTR pszPathA, int iLen /*= -1*/)
{
// Just search the last '.'-character which comes after an optionally
// available last '\'-char.
int iPos = iLen >= 0 ? iLen : strlen(pszPathA);
while (iPos-- > 0)
{
if (pszPathA[iPos] == '.')
return &pszPathA[iPos];
if (pszPathA[iPos] == '\\')
break;
}
return NULL;
}
// GetFileExtW -- UNICODE version
//
// This function is thought to be used only for filenames which have been
// validated by 'GetFullPathName' or similar functions.
LPCWSTR GetFileExtW(LPCWSTR pszPathW, int iLen /*= -1*/)
{
// Just search the last '.'-character which comes after an optionally
// available last '\'-char.
int iPos = iLen >= 0 ? iLen : wcslen(pszPathW);
while (iPos-- > 0)
{
if (pszPathW[iPos] == L'.')
return &pszPathW[iPos];
if (pszPathW[iPos] == L'\\')
break;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////////
// PASTEURLDATA
struct PASTEURLDATA
{
PASTEURLDATA()
{
m_eType = (DataType)-1;
m_dwFlags = 0;
}
PASTEURLDATA(BSTR bstrText, DWORD dwFlags = 0)
{
m_eType = HTMLText;
m_bstrURLs = bstrText;
m_dwFlags = dwFlags;
}
PASTEURLDATA(IDispatch *pIDispatch, DWORD dwFlags = 0)
{
m_eType = Document;
m_pIDispDoc = pIDispatch;
m_dwFlags = dwFlags;
}
enum DataType
{
Text,
HTMLText,
Document
} m_eType;
DWORD m_dwFlags;
union
{
BSTR m_bstrURLs;
IDispatch *m_pIDispDoc;
};
};
//////////////////////////////////////////////////////////////////////////////
// CMainFrameDropTarget
CMainFrameDropTarget::CMainFrameDropTarget()
{
m_bDropDataValid = FALSE;
m_cfHTML = (CLIPFORMAT)RegisterClipboardFormat(_T("HTML Format"));
ASSERT(m_cfHTML != 0);
m_cfShellURL = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_SHELLURL);
ASSERT(m_cfShellURL != 0);
}
HRESULT CMainFrameDropTarget::PasteHTMLDocument(IHTMLDocument2* doc, PASTEURLDATA* pPaste)
{
HRESULT hrPasteResult = S_FALSE; // default: nothing was pasted
int iURLElements = 0;
// get_links HREF all <LINK> and <AREA> elements -> that's *wrong* it also contains all <A> elements!
// get_anchors HREF all <A> elements which have a NAME or ID value!
//
// Links
//
CComPtr<IHTMLElementCollection> links;
if (doc->get_links(&links) == S_OK)
{
long lLinks;
if (links->get_length(&lLinks) == S_OK && lLinks > 0)
{
iURLElements += lLinks;
CComVariant vaIndex((long)0);
CComVariant vaNull((long)0);
for (long i = 0; i < lLinks; i++)
{
vaIndex.lVal = i;
CComPtr<IDispatch> item;
if (links->item(vaIndex, vaNull, &item) == S_OK)
{
CComPtr<IHTMLAnchorElement> anchor;
if (SUCCEEDED(item->QueryInterface(&anchor)))
{
CComBSTR bstrHref;
if (anchor->get_href(&bstrHref) == S_OK && bstrHref.Length() > 0 && IsUrlSchemeSupportedW(bstrHref))
{
theApp.emuledlg->ProcessED2KLink(CString(bstrHref));
hrPasteResult = S_OK;
}
anchor.Release(); // conserve memory
}
}
}
}
links.Release(); // conserve memory
}
//
// Text
//
// The explicit handling of text is needed, if we're looking at contents which were copied
// to the clipboard in HTML format -- although it is simple raw text!! This situation applies,
// if the user opens the "View Partial Source" HTML window for some selected HTML contents,
// and copies some text (e.g. an URL) to the clipboard. In that case we'll get the raw text
// as HTML contents!!!
//
// PROBLEM: We can *not* always process the HTML elements (anchors, ...) *and* the inner text.
// The following example (a rather *usual* one) would lead to the adding of the same URL twice
// because the URL is noted as a HREF *and* as the inner text.
//
// <P><A href="http://www.domain.com/image.gif">http://www.domain.com/image.gif</A></P>
//
// So, in practice, the examination of the 'innerText' is only done, if there were no other
// HTML elements in the document.
//
if (iURLElements == 0)
{
CComPtr<IHTMLElement> el;
if (doc->get_body(&el) == S_OK)
{
CComBSTR bstr;
if (el->get_innerText(&bstr) == S_OK && bstr.Length() > 0)
{
LPCWSTR pwsz = bstr;
while (*pwsz != L'\0' && iswspace(*pwsz)) // Skip white spaces
pwsz++;
// PROBLEM: The 'innerText' does not contain any HTML tags, but it *MAY* contain
// HTML comments like "<!--StartFragment-->...<!--EndFragment-->". Those
// tags have to be explicitly parsed to get the real raw text contents.
// Those Start- and End-tags are available if the text is copied into the clipboard
// from a HTML window which was open with "View Partial Source"!
static const WCHAR _wszStartFrag[] = L"<!--StartFragment-->";
if (wcsncmp(pwsz, _wszStartFrag, ARRSIZE(_wszStartFrag)-1) == 0)
{
pwsz += ARRSIZE(_wszStartFrag)-1;
// If there's a Start-tag, search for an End-tag.
static const WCHAR _wszEndFrag[] = L"<!--EndFragment-->";
LPWSTR pwszEnd = (LPWSTR)bstr + bstr.Length();
pwszEnd -= ARRSIZE(_wszEndFrag)-1;
if (pwszEnd >= pwsz)
{
if (wcsncmp(pwszEnd, _wszEndFrag, ARRSIZE(_wszEndFrag)-1) == 0)
*pwszEnd = L'\0'; // Ugly but efficient, terminate the BSTR!
}
}
// Search all white-space terminated strings and check for a valid URL-scheme
while (*pwsz != L'\0')
{
while (*pwsz != L'\0' && iswspace(*pwsz)) // Skip white spaces
pwsz++;
if (IsUrlSchemeSupportedW(pwsz))
{
LPCWSTR pwszEnd = pwsz;
while (*pwszEnd != L'\0' && !iswspace(*pwszEnd)) // Search next white space (end of current string)
pwszEnd++;
int iLen = pwszEnd - pwsz;
if (iLen > 0)
{
CString strURL(pwsz, iLen);
theApp.emuledlg->ProcessED2KLink(strURL);
hrPasteResult = S_OK;
pwsz += iLen;
}
}
else
{
while (*pwsz != L'\0' && !iswspace(*pwsz)) // Search next white space (end of current string)
pwsz++;
}
while (*pwsz != L'\0' && iswspace(*pwsz)) // Skip white spaces
pwsz++;
}
}
}
}
return hrPasteResult;
}
HRESULT CMainFrameDropTarget::PasteHTML(PASTEURLDATA* pPaste)
{
HRESULT hrPasteResult = S_FALSE; // default: nothing was pasted
if (pPaste->m_bstrURLs[0] != L'\0')
{
HRESULT hr;
CComPtr<IHTMLDocument2> doc;
if (SUCCEEDED(hr = doc.CoCreateInstance(CLSID_HTMLDocument, NULL)))
{
SAFEARRAY* psfHtmlLines = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (psfHtmlLines != NULL)
{
VARIANT* pva;
if (SafeArrayAccessData(psfHtmlLines, (void**)&pva) == S_OK)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -