// MarkupPadEdit.cpp : implementation file
//
#include "stdafx.h"
#include "resource.h"
#include "MarkupPadEdit.h"
#include "MarkupPadDoc.h"
#include "MarkupPadView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMarkupPadEdit
IMPLEMENT_DYNCREATE(CMarkupPadEdit, CEditView)
CMarkupPadEdit::CMarkupPadEdit()
{
m_hInstance = LoadLibraryA("RICHED20.DLL");
if (m_hInstance)
{
#ifdef _UNICODE
m_strClass = _T("RichEdit20W");
#else
m_strClass = _T("RichEdit20A");
#endif
}
else
{
m_hInstance = LoadLibraryA("RICHED32.DLL");
m_strClass = _T("RICHEDIT");
}
NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
STRCPY_S(ncm.lfMessageFont.lfFaceName, LF_FACESIZE, _T("Courier New"));
ncm.lfMessageFont.lfHeight = -14;
m_fnt.CreateFontIndirect(&ncm.lfMessageFont);
m_bFirstDoc = TRUE;
m_bError = FALSE;
}
CMarkupPadEdit::~CMarkupPadEdit()
{
}
BEGIN_MESSAGE_MAP(CMarkupPadEdit, CEditView)
//{{AFX_MSG_MAP(CMarkupPadEdit)
ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
ON_WM_CONTEXTMENU()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMarkupPadEdit diagnostics
#ifdef _DEBUG
void CMarkupPadEdit::AssertValid() const
{
CEditView::AssertValid();
}
void CMarkupPadEdit::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMarkupPadEdit message handlers
void CMarkupPadEdit::OnInitialUpdate()
{
CEditView::OnInitialUpdate();
SetFont(&m_fnt);
SendMessage(EM_SETTEXTMODE, TM_PLAINTEXT | TM_MULTILEVELUNDO);
SendMessage(EM_SETEVENTMASK, 0, ENM_CHANGE);
if (m_bFirstDoc)
{
CFrameWnd* pMainFrame = (CFrameWnd*)AfxGetMainWnd();
if (pMainFrame)
{
CXTPStatusBar* pStatusBar = (CXTPStatusBar*)pMainFrame->GetDlgItem(AFX_IDW_STATUS_BAR);
pStatusBar->GetMarkupContext()->AddHandler(CXTPMarkupHyperlink::m_pClickEvent, CreateMarkupClassDelegate(this, &CMarkupPadEdit::OnStatusBarHyperlinkClick));
}
}
if (GetDocument()->GetPathName().IsEmpty() && m_bFirstDoc)
{
SetWindowText(_T("\r\n Enter Text Here\r\n"));
}
m_bFirstDoc = FALSE;
OnChange();
GetDocument()->SetModifiedFlag(FALSE);
}
LPWSTR CMarkupPadEdit::GetUnicodeText()
{
GETTEXTLENGTHEX gtl =
{
GTL_DEFAULT, 1200
};
int nLen = (int)SendMessage(EM_GETTEXTLENGTHEX, (WPARAM)>l);
if (nLen > 0)
{
GETTEXTEX gt =
{
(nLen + 1) * sizeof(WCHAR), GT_DEFAULT, 1200, 0, 0
};
LPWSTR lpBuffer = new WCHAR[nLen + 1];
SendMessage(EM_GETTEXTEX, (WPARAM)>, (LPARAM)lpBuffer);
return lpBuffer;
}
return NULL;
}
CString CreateMarkupError(LPCTSTR lpszLastError)
{
LPCTSTR lpszIndex = _tcsstr(lpszLastError, _T(". Line "));
if (lpszIndex == NULL)
return lpszLastError;
((LPTSTR)lpszIndex)[1] = 0;
CString str;
str.Format(_T("%s %s"), lpszLastError, lpszIndex + 2);
((LPTSTR)lpszIndex)[1] = ' ';
return str;
}
void CMarkupPadEdit::OnChange()
{
USES_CONVERSION;
CMarkupPadDoc* pDocument = (CMarkupPadDoc*)GetDocument();
POSITION pos = pDocument->GetFirstViewPosition();
CMarkupPadView* pView = (CMarkupPadView*)pDocument->GetNextView(pos);
LPWSTR lpszMarkup = GetUnicodeText();
_int64 nPerfomanceEnd;
_int64 nPerfomanceStart;
QueryPerformanceCounter((LARGE_INTEGER*)&nPerfomanceStart);
CXTPMarkupParser sc;
if (lpszMarkup) sc.SetBuffer(lpszMarkup, lpszMarkup + wcslen(lpszMarkup));
CXTPMarkupBuilder builder(pView);
CXTPMarkupUIElement* pUIElement = builder.Parse(&sc);
if (lpszMarkup)
delete[] lpszMarkup;
QueryPerformanceCounter((LARGE_INTEGER*)&nPerfomanceEnd);
TRACE(_T("Parse = %i \n"), int(nPerfomanceEnd - nPerfomanceStart));
BOOL bError = m_bError;
if (pUIElement)
{
MARKUP_RELEASE(pView->m_pUIElement);
pView->m_pUIElement = pUIElement;
bError = FALSE;
UpdateViews();
GetParentFrame()->SetMessageText(_T("Done."));
}
else
{
bError = TRUE;
GetParentFrame()->SetMessageText(CreateMarkupError(builder.GetLastError()));
}
if (m_bError != bError)
{
m_bError = bError;
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.crTextColor = m_bError ? RGB(255, 0, 0) : 0;
SendMessage(EM_SETCHARFORMAT, 0, (LPARAM)&cf);
}
pDocument->SetModifiedFlag(TRUE);
}
void CMarkupPadEdit::UpdateViews()
{
CDocument* pDocument = GetDocument();
POSITION pos = pDocument->GetFirstViewPosition();
while (pos)
{
CView* pView = pDocument->GetNextView(pos);
if (pView != this)
{
pView->Invalidate(FALSE);
break;
}
}
}
void CMarkupPadEdit::OnStatusBarHyperlinkClick(CXTPMarkupObject* pSender, CXTPMarkupRoutedEventArgs* pArgs)
{
if (pSender->IsKindOf(MARKUP_TYPE(CXTPMarkupHyperlink)))
{
CXTPMarkupRun* pRun = (CXTPMarkupRun*)((CXTPMarkupHyperlink*)pSender)->GetInlines()->GetInline(0);
CString strText = pRun->GetText();
int nLine = 0, nPosition = 0;
if (SCANF_S(strText, _T("Line %i, position %i"), &nLine, &nPosition) == 2)
{
int nPos = nPosition + (int)SendMessage(EM_LINEINDEX, nLine - 1);
SendMessage(EM_SETSEL, nPos, nPos);
}
pArgs->SetHandled();
}
}
void CMarkupPadEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
CMenu menu;
menu.LoadMenu(IDR_MENU_CONTEXT);
if (point == CPoint(-1, -1))
GetCursorPos(&point);
((CXTPFrameWnd*)AfxGetMainWnd())->GetCommandBars()->TrackPopupMenuEx(menu.GetSubMenu(0), 0, point.x, point.y, pWnd);
}