📄 hypertextctrl.cpp
字号:
/********************************************************************
HyperTextCtrl.h - Controls that shows hyperlinks
in text
Copyright (C) 2001-2002 Magomed G. Abdurakhmanov
********************************************************************/
//edited by (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//-> converted it to MFC
//-> included colored keywords
//-> fixed GPF bugs
//-> made it flickerfree
//-> some other small changes
// (the whole code still needs some work though)
//
//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 "hypertextctrl.h"
#include <deque>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// CHyperLink
CHyperLink::CHyperLink(int iBegin, uint16 iEnd, const CString& sTitle, const CString& sCommand, const CString& sDirectory){
m_Type = lt_Shell;
m_iBegin = iBegin;
m_iEnd = iEnd;
m_sTitle = sTitle;
m_sCommand = sCommand;
m_sDirectory = sDirectory;
// [i_a] used for lt_Message
m_hWnd = 0;
m_uMsg = 0;
m_wParam = 0;
m_lParam = 0;
} // [/i_a]
CHyperLink::CHyperLink(int iBegin, uint16 iEnd, const CString& sTitle, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
m_Type = lt_Message;
m_iBegin = iBegin;
m_iEnd = iEnd;
m_sTitle = sTitle;
m_hWnd = hWnd;
m_uMsg = uMsg;
m_wParam = wParam;
m_lParam = lParam;
}
CHyperLink::CHyperLink(){ // [i_a]
m_Type = lt_Unknown;
m_iBegin = 0;
m_iEnd = 0;
m_sTitle.Empty();
m_sCommand.Empty();
m_sDirectory.Empty();
m_hWnd = 0;
m_uMsg = 0;
m_wParam = 0;
m_lParam = 0;
} // [/i_a]
CHyperLink::CHyperLink(const CHyperLink& Src){
m_Type = Src.m_Type;
m_iBegin = Src.m_iBegin;
m_iEnd = Src.m_iEnd;
m_sTitle = Src.m_sTitle;
m_sCommand = Src.m_sCommand;
m_sDirectory = Src.m_sDirectory;
m_hWnd = Src.m_hWnd;
m_uMsg = Src.m_uMsg;
m_wParam = Src.m_wParam;
m_lParam = Src.m_lParam;
}
void CHyperLink::Execute(){
switch(m_Type)
{
case lt_Shell:
ShellExecute(NULL, NULL, m_sCommand, NULL, m_sDirectory, SW_SHOWDEFAULT);
break;
case lt_Message:
PostMessage(m_hWnd, m_uMsg, m_wParam, m_lParam);
break;
}
}
// CKeyWord
CKeyWord::CKeyWord(int iBegin, uint16 iEnd, COLORREF icolor){
color = icolor;
m_iBegin = iBegin;
m_iEnd = iEnd;
}
// CPreparedHyperText
void CPreparedHyperText::PrepareText(const CString& sText)
{
m_sText = sText;
m_Links.clear();
enum {
unknown,
space,
http0, /* http:// */
http1, http2, http3, http4, http5, http6,
ftp0, /* ftp:// */
ftp1, ftp2, ftp3, ftp4, ftp5,
ftp, /* ftp. */
www0, /* www. */
www1, www2, www3,
mailto0, /* mailto: */
mailto1, mailto2, mailto3, mailto4, mailto5, mailto6,
mail, /* xxx@yyy */
ed2k0, /* ed2k:// */
ed2k1, ed2k2, ed2k3, ed2k4, ed2k5, ed2k6
} state = space;
int WordPos = 0;
TCHAR sz[2];
TCHAR& c = sz[0];
sz[1] = 0;
int last = m_sText.GetLength() -1;
for(int i = 0; i <= last; i++)
{
c = m_sText[i];
_tcslwr(sz);
switch(state)
{
case unknown:
if(tspace(c))
state = space;
else
if(c == _T('@') && WordPos != i)
state = mail;
break;
case space:
WordPos = i;
switch(c)
{
case _T('h'): state = http0; break;
case _T('f'): state = ftp0; break;
case _T('w'): state = www0; break;
case _T('m'): state = mailto0; break;
case _T('e'): state = ed2k0; break;
default:
if(!tspace(c))
state = unknown;
}
break;
/*----------------- http -----------------*/
case http0:
if(c == _T('t'))
state = http1;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case http1:
if(c == _T('t'))
state = http2;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case http2:
if(c == _T('p'))
state = http3;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case http3:
if(c == _T(':'))
state = http4;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case http4:
if(c == _T('/'))
state = http5;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case http5:
if(c == _T('/'))
state = http6;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case http6:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
/*----------------- ed2k -----------------*/
case ed2k0:
if(c == _T('d'))
state = ed2k1;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ed2k1:
if(c == _T('2'))
state = ed2k2;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ed2k2:
if(c == _T('k'))
state = ed2k3;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ed2k3:
if(c == _T(':'))
state = ed2k4;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ed2k4:
if(c == _T('/'))
state = ed2k5;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ed2k5:
if(c == _T('/'))
state = ed2k6;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ed2k6:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
/*----------------- ftp -----------------*/
case ftp0:
if(c == _T('t'))
state = ftp1;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ftp1:
if(c == _T('p'))
state = ftp2;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ftp2:
if(c == _T(':'))
state = ftp3;
else
if(c == _T('.'))
state = ftp;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ftp3:
if(c == _T('/'))
state = ftp4;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ftp4:
if(c == _T('/'))
state = ftp5;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case ftp:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = CString(_T("ftp://")) + m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
case ftp5:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
/*----------------- www -----------------*/
case www0:
if(c == _T('w'))
state = www1;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case www1:
if(c == _T('w'))
state = www2;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case www2:
if(c == _T('.'))
state = www3;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case www3:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = CString(_T("http://")) + m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
/*----------------- mailto -----------------*/
case mailto0:
if(c == _T('a'))
state = mailto1;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case mailto1:
if(c == _T('i'))
state = mailto2;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case mailto2:
if(c == _T('l'))
state = mailto3;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case mailto3:
if(c == _T('t'))
state = mailto4;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case mailto4:
if(c == _T('o'))
state = mailto5;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case mailto5:
if(c == _T(':'))
state = mailto6;
else
if(tspace(c))
state = space;
else
state = unknown;
break;
case mailto6:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
/*----------------- mailto -----------------*/
case mail:
if(tspace(c) || i == last)
{
int len = i == last ? i - WordPos + 1 : i - WordPos;
CString s = CString(_T("mailto:")) + m_sText.Mid(WordPos, len);
RemoveLastSign(s);
m_Links.push_back(CHyperLink(WordPos, WordPos + len - 1, s, s, (LPCTSTR)NULL));
state = space;
}
break;
}
}
m_Links.sort();
}
void CPreparedHyperText::RemoveLastSign(CString& sLink)
{
int len = sLink.GetLength();
if(len > 0)
{
TCHAR c = sLink[len-1];
switch(c)
{
case _T('.'):
case _T(','):
case _T(';'):
case _T('\"'):
case _T('\''):
case _T('('):
case _T(')'):
case _T('['):
case _T(']'):
case _T('{'):
case _T('}'):
sLink.Delete(len -1, 1);
break;
}
}
}
CPreparedHyperText::CPreparedHyperText(const CString& sText){
PrepareText(sText);
}
CPreparedHyperText::CPreparedHyperText(const CPreparedHyperText& src){
m_sText = src.m_sText;
m_Links.assign(src.m_Links.begin(), src.m_Links.end());
}
void CPreparedHyperText::Clear(){
m_sText.Empty();
m_Links.erase(m_Links.begin(), m_Links.end());
}
void CPreparedHyperText::SetText(const CString& sText){
Clear();
PrepareText(sText);
}
void CPreparedHyperText::AppendText(const CString& sText){
int len = m_sText.GetLength();
////////////////////////////////////////////////
//Top:The Original code didn't check to see if the buffer was full..
////////////////////////////////////////////////
bool flag = true;
if( len > 60000 ){
m_sText = m_sText.Right(50000);
int shift = len - m_sText.GetLength();
while( flag == true ){
CHyperLink &test = m_Links.front();
if( !m_Links.empty() ){
if( test.Begin() < shift )
m_Links.pop_front();
else
flag = false;
}
else
flag = false;
}
flag = true;
while( flag == true ){
CKeyWord &test = m_KeyWords.front();
if( !m_KeyWords.empty() ){
if( test.Begin() < shift )
m_KeyWords.pop_front();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -