DragonNest/Third/XTToolkitPro/Samples/Utilities/StylerBrowser/SourceCtrl.cpp
2024-12-19 09:48:26 +08:00

250 lines
4.5 KiB
C++

// SourceCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "styler.h"
#include "SourceCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSourceCtrl
CSourceCtrl::CSourceCtrl()
{
LOGFONT lfIcon;
VERIFY( ::SystemParametersInfo( SPI_GETICONTITLELOGFONT, sizeof( lfIcon ), &lfIcon, 0 ) );
VERIFY( m_fntText.CreateFontIndirect(&lfIcon ) );
}
CSourceCtrl::~CSourceCtrl()
{
}
BOOL CSourceCtrl::Create(CWnd* pParent)
{
if (!CRichEditCtrl::Create(WS_VSCROLL | WS_HSCROLL| WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL | ES_SAVESEL | ES_READONLY ,
CRect(0,0,0,0), pParent, 1))
{
return FALSE;
}
SetBackgroundColor(FALSE, GetSysColor(COLOR_3DFACE));
SetFont(&m_fntText, FALSE);
return TRUE;
}
void CSourceCtrl::Refresh(CHtmlView* pView, BOOL /*bForce*/)
{
USES_CONVERSION;
HRESULT hr;
LPDISPATCH lpDisp = pView->GetHtmlDocument();
if (!lpDisp)
return;
// Verify that what we get is a pointer to a IHTMLDocument2
// interface. To be sure, let's query for
// the IHTMLDocument2 interface (through smart pointers)
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spHTML(lpDisp);
// The previous step is sufficient to keep Explorer aside
// without an explicit check against the loader module
// Extract the source code of the document
CComPtr<IHTMLElement> m_pBody = NULL;
if (spHTML)
{
// Get the BODY object
hr = spHTML->get_body(&m_pBody);
if (FAILED(hr) || !m_pBody)
return;
// Get the HTML text
BSTR bstrHTMLText;
hr = m_pBody->get_outerHTML(&bstrHTMLText);
if (FAILED(hr))
return;
// Convert the text from Unicode to ANSI
int nLength = SysStringLen(bstrHTMLText);
LPTSTR psz = new TCHAR[nLength + 1];
lstrcpy(psz, OLE2T(bstrHTMLText));
SetTextFormat(psz);
delete [] psz;
}
else // The document isn't a HTML page
{
}
lpDisp->Release();
}
void AddLine(CStringArray& sa, LPTSTR pStart, int nCount)
{
CString str;
LPTSTR pLine = str.GetBufferSetLength(nCount);
STRNCPY_S(pLine, nCount + 1, pStart, nCount);
pLine[nCount] = 0;
str.TrimLeft();
if (str != "")
sa.Add(str);
}
CString GetTag(CString str)
{
str.TrimLeft();
if (str.IsEmpty() || str[0] != _T('<'))
return _T("");
int nStart = 1;
while (nStart < str.GetLength() && str[nStart] == ' ') nStart++;
int nEnd = str.Find(' ', nStart);
int nTag = str.Find('>', nStart);
if (nEnd != -1)
{
if (nTag != -1)
nEnd = min(nEnd, nTag);
} else nEnd = nTag;
if (nEnd == -1)
{
return _T("");
}
CString strTag = str.Mid(nStart, nEnd - nStart);
return strTag;
}
void Format(CStringArray& sa)
{
for (int i = 0; i < sa.GetSize(); i++)
{
CString& strNext = sa[i];
CString strTag = GetTag(strNext);
if (!strTag.IsEmpty() && strTag[0] == '/')
{
CString strClose = strTag.Right(strTag.GetLength() - 1);
int nRefCount = 1;
int k = i - 1;
while (k >= 0)
{
CString& str = sa[k];
CString strOpen = GetTag(str);
if (strOpen == strTag) nRefCount ++;
if (strOpen == strClose)
{
nRefCount --;
if (nRefCount == 0) break;
}
k--;
}
if (k>= 0)
{
while (++k < i)
{
sa[k] = _T(" ") + sa[k];
}
}
}
}
}
void CSourceCtrl::SetTextFormat(LPTSTR pText)
{
CStringArray sa;
CString str;
TCHAR* pChar = pText;
TCHAR* pStart = pText;
while (*pChar)
{
if (*pChar == '<' && pStart != pChar)
{
AddLine(sa, pStart, (int)(pChar - pStart));
pStart = pChar;
} else
if (*pChar == '>')
{
AddLine(sa, pStart, int(pChar - pStart + 1));
pStart = pChar + 1;
}
if (*pChar == '\n' || *pChar == '\r')
*pChar = ' ';
pChar ++;
}
if (pChar!=pStart)
{
AddLine(sa, pStart, int(pChar - pStart));
}
Format(sa);
LockWindowUpdate();
SetSel(0, -1);
Clear();
CString strBody;
for (int i = 0; i < sa.GetSize(); i++)
{
strBody = sa[i] + _T("\r\n");
if (strBody.Find('<') == -1)
{
CHARFORMAT cf;
cf.cbSize = sizeof CHARFORMAT;
cf.dwMask = CFM_BOLD;
cf.dwEffects = CFE_BOLD;
SetSelectionCharFormat (cf);
}
ReplaceSel(strBody);
}
UnlockWindowUpdate();
}
BEGIN_MESSAGE_MAP(CSourceCtrl, CRichEditCtrl)
//{{AFX_MSG_MAP(CSourceCtrl)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSourceCtrl message handlers