// MarkupPadEdit.cpp
//
// (c)1998-2025 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "resource.h"
#include "MarkupPadEdit.h"
#include "MarkupPadDoc.h"
#include "MarkupPadView.h"
#include "MainFrm.h"
#ifdef _DEBUG
# define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMarkupPadEdit
IMPLEMENT_DYNCREATE(CMarkupPadEdit, CXTPSyntaxEditView)
CMarkupPadEdit::CMarkupPadEdit()
: m_pPane(NULL)
{
CXTPNonClientMetrics ncm;
STRCPY_S(ncm.lfMessageFont.lfFaceName, LF_FACESIZE, _T("Courier New"));
ncm.lfMessageFont.lfHeight = -XTP_DPI_Y(14);
m_fnt.CreateFontIndirect(&ncm.lfMessageFont);
m_bFirstDoc = TRUE;
m_bError = FALSE;
}
CMarkupPadEdit::~CMarkupPadEdit()
{
}
BEGIN_MESSAGE_MAP(CMarkupPadEdit, CXTPSyntaxEditView)
//{{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
{
CXTPSyntaxEditView::AssertValid();
}
void CMarkupPadEdit::Dump(CDumpContext& dc) const
{
CXTPSyntaxEditView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMarkupPadEdit message handlers
void CMarkupPadEdit::OnInitialUpdate()
{
CXTPSyntaxEditView::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)
{
GetEditCtrl().SetText(
_T("\r\n")
_T(" Enter Text Here\r\n"));
}
m_bFirstDoc = FALSE;
OnChange();
GetDocument()->SetModifiedFlag(FALSE);
}
void CMarkupPadEdit::SetOwnerPane(CXTPDockingPane* pPane)
{
_ASSERTE(pPane);
m_pPane = pPane;
}
void CMarkupPadEdit::RefreshColors(UINT nTheme)
{
CString sIni = _T("EditConfig\\SyntaxEdit.ini");
CString sSchema = _T("EditConfig\\Schemas\\_XAML.schclass");
COLORREF clrBackColor;
COLORREF clrLineNumberBackColor;
COLORREF clrLineNumberTextColor;
switch (nTheme)
{
case ID_THEMEOFFICE2016_COLORFUL_ACCESS:
case ID_THEMEOFFICE2016_COLORFUL_EXCEL:
case ID_THEMEOFFICE2016_COLORFUL_ONENOTE:
case ID_THEMEOFFICE2016_COLORFUL_OUTLOOK:
case ID_THEMEOFFICE2016_COLORFUL_POWERPOINT:
case ID_THEMEOFFICE2016_COLORFUL_PUBLISHER:
case ID_THEMEOFFICE2016_COLORFUL_WORD:
case ID_THEMEOFFICE2016_WHITE_ACCESS:
case ID_THEMEOFFICE2016_WHITE_EXCEL:
case ID_THEMEOFFICE2016_WHITE_ONENOTE:
case ID_THEMEOFFICE2016_WHITE_OUTLOOK:
case ID_THEMEOFFICE2016_WHITE_POWERPOINT:
case ID_THEMEOFFICE2016_WHITE_PUBLISHER:
case ID_THEMEOFFICE2016_WHITE_WORD:
case ID_THEMEOFFICE2016_DARKGRAY_ACCESS:
case ID_THEMEOFFICE2016_DARKGRAY_EXCEL:
case ID_THEMEOFFICE2016_DARKGRAY_ONENOTE:
case ID_THEMEOFFICE2016_DARKGRAY_OUTLOOK:
case ID_THEMEOFFICE2016_DARKGRAY_POWERPOINT:
case ID_THEMEOFFICE2016_DARKGRAY_PUBLISHER:
case ID_THEMEOFFICE2016_DARKGRAY_WORD:
clrBackColor = RGB(246, 246, 246);
clrLineNumberBackColor = RGB(246, 246, 246);
clrLineNumberTextColor = RGB(43, 145, 175);
break;
case ID_THEMEOFFICE2016_BLACK_ACCESS:
case ID_THEMEOFFICE2016_BLACK_EXCEL:
case ID_THEMEOFFICE2016_BLACK_ONENOTE:
case ID_THEMEOFFICE2016_BLACK_OUTLOOK:
case ID_THEMEOFFICE2016_BLACK_POWERPOINT:
case ID_THEMEOFFICE2016_BLACK_PUBLISHER:
case ID_THEMEOFFICE2016_BLACK_WORD:
clrBackColor = RGB(28, 28, 28);
clrLineNumberBackColor = RGB(28, 28, 28);
clrLineNumberTextColor = RGB(86, 156, 214);
break;
default:
clrBackColor = RGB(255, 255, 255);
clrLineNumberBackColor = RGB(255, 255, 255);
clrLineNumberTextColor = RGB(43, 145, 175);
break;
}
GetEditCtrl().GetPaintManager()->SetBackColor(clrBackColor, FALSE);
GetEditCtrl().GetPaintManager()->SetLineNumberBackColor(clrLineNumberBackColor, FALSE);
GetEditCtrl().GetPaintManager()->SetLineNumberTextColor(clrLineNumberTextColor, FALSE);
GetEditCtrl().SetSelMargin(FALSE);
if (GetEditCtrl().GetEditBuffer())
GetEditCtrl().GetEditBuffer()->SetFileExt(_T(".XAML"));
GetEditCtrl().SetConfigFile(CXTPSyntaxEditCtrl::GetModulePath() + sIni, TRUE);
{
CStdioFile file;
CString strLine;
CString strINI;
CString strSchema;
if (file.Open(CXTPSyntaxEditCtrl::GetModulePath() + sIni, CFile::modeRead))
{
while (file.ReadString(strLine))
{
strINI += strLine + _T("\r\n");
}
file.Close();
}
else
{
AfxMessageBox(_T("Could not load file"));
}
strLine = _T("");
strSchema = _T("");
if (file.Open(CXTPSyntaxEditCtrl::GetModulePath() + sSchema, CFile::modeRead))
{
while (file.ReadString(strLine))
{
strSchema += strLine + _T("\r\n");
}
file.Close();
}
else
{
AfxMessageBox(_T("Could not load file"));
}
GetEditCtrl().SetSyntaxAndColorScheme(strSchema, strINI, FALSE, FALSE);
}
}
LRESULT CMarkupPadEdit::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_NCPAINT)
{
CXTPSyntaxEditView::WindowProc(message, wParam, lParam);
CWindowDC dc(this);
CXTPWindowRect rWindow(this);
rWindow.OffsetRect(-rWindow.TopLeft());
theApp.m_csPane.DrawBorders(&dc, rWindow, m_pPane);
return TRUE;
}
return CXTPSyntaxEditView::WindowProc(message, wParam, lParam);
}
LPWSTR CMarkupPadEdit::GetUnicodeText()
{
if (!GetEditCtrl().GetText().IsEmpty())
{
#ifdef UNICODE
int len = GetEditCtrl().GetText().GetLength();
LPWSTR lpBuffer = new WCHAR[len + 1];
STRCPY_S(lpBuffer, XTPToSizeTChecked(len) + 1, GetEditCtrl().GetText());
return lpBuffer;
#else
UINT nCodePage = XTPResourceManager()->GetLanguageInfo()->nCodePage;
int nDestLen = MultiByteToWideChar(nCodePage, 0, GetEditCtrl().GetText(), -1, NULL, 0);
WCHAR* lpBuffer = new WCHAR[XTPToUIntChecked(nDestLen)];
MultiByteToWideChar(nCodePage, 0, GetEditCtrl().GetText(), -1, lpBuffer, nDestLen);
return lpBuffer;
#endif
}
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(200, 0, 0) : theApp.m_csPane.m_clrMarkupText;
SendMessage(EM_SETCHARFORMAT, 0, (LPARAM)&cf);
SendMessage(EM_SETBKGNDCOLOR, 0, (LPARAM)theApp.m_csPane.m_clrBack);
}
else
{
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.crTextColor = m_bError ? RGB(200, 0, 0) : theApp.m_csPane.m_clrMarkupText;
SendMessage(EM_SETCHARFORMAT, 0, (LPARAM)&cf);
SendMessage(EM_SETBKGNDCOLOR, 0, (LPARAM)theApp.m_csPane.m_clrBack);
}
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);
}
BOOL CMarkupPadEdit::OnEditChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
XTP_EDIT_NMHDR_EDITCHANGED* pNMHDR_EC = (XTP_EDIT_NMHDR_EDITCHANGED*)pNMHDR;
UpdateSiblings(pNMHDR_EC);
OnChange();
*pResult = 1;
return TRUE;
}