?// PaneEditorWnd.cpp : implementation file
//
#include "stdafx.h"
#include "grammarIDE.h"
#include "grammarIDEDoc.h"
#include "PaneEditorWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPaneEditorWnd dialog
UINT CPaneEditorWnd::WMU_FORMATLINES = 0;
CPaneEditorWnd::CPaneEditorWnd(CGrammarIDEDoc* pDoc, CWnd* pParent /*=NULL*/)
: CDialog(CPaneEditorWnd::IDD, pParent),
m_pDoc(pDoc)
{
if(WMU_FORMATLINES==0)
WMU_FORMATLINES = RegisterWindowMessage(_T("WMU_FORMATLINES"));
//{{AFX_DATA_INIT(CPaneEditorWnd)
m_nSection = -1;
//}}AFX_DATA_INIT
m_nFmtMin = -1;
m_nFmtMax = -1;
m_fModified = false;
}
void CPaneEditorWnd::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPaneEditorWnd)
DDX_Control(pDX, IDC_RICHEDIT, m_richEdit);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPaneEditorWnd, CDialog)
//{{AFX_MSG_MAP(CPaneEditorWnd)
ON_WM_SIZE()
ON_NOTIFY(EN_PROTECTED, IDC_RICHEDIT, OnProtectedRichEdit)
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(WMU_FORMATLINES, OnFormatLines)
END_MESSAGE_MAP()
LPCTSTR g_lpszSections[]={"[tokens]","[seperators]","[rules]","[grammar]",NULL};
/////////////////////////////////////////////////////////////////////////////
// CPaneEditorWnd operations
void CPaneEditorWnd::Renumber(bool fStrict)
{
if(GetSafeHwnd()==NULL)
return;
CHARRANGE crPrev;
m_richEdit.LockWindowUpdate();
m_richEdit.GetSel(crPrev);
int i, lines = m_richEdit.GetLineCount();
int nCurID = 0;
TCHAR szTemp[512];
for(i=0;i<lines;i++)
{
if(IsSectionLine(i))
continue;
if(!IsLineWellFormed(i))
continue;
CHARRANGE cr;
std::tstring strLine;
m_richEdit.GetLine(i,szTemp,510);
szTemp[511]='\0';
strLine = szTemp;
cr.cpMin = m_richEdit.LineIndex(i);
cr.cpMax = m_richEdit.LineIndex(i+1);
m_richEdit.SetSel(cr);
std::tstring::size_type pos = strLine.find(':');
ASSERT(pos!=std::tstring::npos);
int nLineID = _ttoi(strLine.substr(0,pos).c_str());
if(nLineID!=0)
{
bool fInvert = (nLineID<0);
nLineID = fInvert?-nLineID:nLineID;
nCurID++;
TCHAR szBuf[32];
if(nLineID>nCurID && !fStrict) nCurID=nLineID;
_itot( (fInvert)?-nCurID:nCurID,szBuf,10);
strLine = std::tstring(szBuf)+strLine.substr(pos);
m_richEdit.ReplaceSel(strLine.c_str(),FALSE);
FormatLine(i);
}
}
m_richEdit.SetSel(crPrev);
m_richEdit.UnlockWindowUpdate();
}
void CPaneEditorWnd::SetSection(esection eSection)
{
if(GetSafeHwnd()==NULL)
return;
UpdateData(TRUE);
switch(eSection)
{
case section_tokens:
m_nSection=0;
break;
case section_seperators:
m_nSection=1;
break;
case section_rules:
m_nSection=2;
break;
case section_grammar:
m_nSection=3;
break;
default:
ASSERT(FALSE);
break;
}
UpdateData(FALSE);
}
bool CPaneEditorWnd::IsInIdRange(int pos)
{
TCHAR szTemp[256]; szTemp[255]='\0';
int line = m_richEdit.LineFromChar(pos);
int lpos = pos-m_richEdit.LineIndex(line);
int j;
m_richEdit.GetLine(line,szTemp,255);
for(j=0;g_lpszSections[j]!=NULL;j++)
if(_tcslen(szTemp)>2 && _tcsncmp(szTemp,g_lpszSections[j],_tcslen(szTemp)-2)==0)
return false;
TCHAR *tmp = _tcschr(szTemp,':');
int dotpos = (tmp!=NULL)?(tmp-szTemp):-1;
if(lpos<=dotpos)
return true;
return false;
}
bool CPaneEditorWnd::IsSectionLine(int nLine)
{
TCHAR szTemp[256]; szTemp[255]='\0';
m_richEdit.GetLine(nLine,szTemp,255);
for(int j=0;g_lpszSections[j]!=NULL;j++)
if(_tcslen(szTemp)>2 && _tcsncmp(szTemp,g_lpszSections[j],_tcslen(szTemp)-2)==0)
return true;
return false;
}
bool CPaneEditorWnd::IsLineWellFormed(int nLine)
{
TCHAR szTemp[256]; szTemp[255]='\0';
m_richEdit.GetLine(nLine,szTemp,255);
bool fMinus = false;
int i, len = _tcslen(szTemp);
for(i=0;i<len;i++)
{
if(szTemp[i]=='-')
{
if(fMinus)
return false;
fMinus=true;
continue;
}
if(szTemp[i]==':')
break;
if(!isdigit(szTemp[i]))
return false;
}
if(i<(len-2))
return true;
return false;
}
void CPaneEditorWnd::FormatLine(int nLine)
{
TCHAR szTemp[256]; szTemp[255]='\0';
int lStart = m_richEdit.LineIndex(nLine);
int lEnd = m_richEdit.LineIndex(nLine+1);
m_richEdit.GetLine(nLine,szTemp,255);
CHARFORMAT cf;
ZeroMemory(&cf,sizeof(cf));
// Is the line commented out?
if(szTemp[0]=='\'')
{
ZeroMemory(&cf,sizeof(cf));
cf.cbSize =sizeof(cf);
cf.dwMask =CFM_FACE|CFM_COLOR|CFM_PROTECTED|CFM_UNDERLINE|CFM_ITALIC;
cf.dwEffects =CFE_PROTECTED|CFE_UNDERLINE|CFE_ITALIC;
cf.crTextColor =RGB(0,128,0);
_tcscpy(cf.szFaceName,_T("Courier New"));
m_richEdit.SetSel(lStart,lEnd);
m_richEdit.SetSelectionCharFormat(cf);
return;
}
// Is the line one of the section lines?
bool fSectionLine = false;
for(int j=0;g_lpszSections[j]!=NULL;j++)
if(_tcslen(szTemp)>2 && _tcsncmp(szTemp,g_lpszSections[j],_tcslen(g_lpszSections[j]))==0)
{ fSectionLine = true; break; };
// Unprotect the line if not a section line (by pressing ENTER at the
// end of a protected section line, the following line gets also protected)
if(!fSectionLine)
{
cf.cbSize =sizeof(cf);
//cf.dwMask =CFM_UNDERLINE;
// Is the line well-formed?
if(IsLineWellFormed(nLine))
{
int pos = _tcschr(szTemp,':')-szTemp;
ZeroMemory(&cf,sizeof(cf));
cf.cbSize =sizeof(cf);
cf.dwMask =CFM_COLOR|CFM_UNDERLINE|CFM_ITALIC;
cf.dwEffects=0;
if(szTemp[0]=='-') cf.crTextColor=RGB(255,128,64);
else cf.crTextColor=RGB(0,128,0);
m_richEdit.SetSel(lStart,lStart+pos);
m_richEdit.SetSelectionCharFormat(cf);
cf.crTextColor=RGB(0,0,0);
m_richEdit.SetSel(lStart+pos,lEnd);
m_richEdit.SetSelectionCharFormat(cf);
}
else
{
ZeroMemory(&cf,sizeof(cf));
cf.cbSize =sizeof(cf);
cf.dwMask =CFM_COLOR|CFM_UNDERLINE|CFM_ITALIC;
cf.dwEffects=CFE_UNDERLINE;
cf.crTextColor =RGB(255,0,0);
m_richEdit.SetSel(lStart,lEnd);
m_richEdit.SetSelectionCharFormat(cf);
}
}
else
{
ZeroMemory(&cf,sizeof(cf));
cf.cbSize =sizeof(cf);
cf.dwMask =CFM_FACE|CFM_COLOR|CFM_PROTECTED|CFM_UNDERLINE|CFM_ITALIC;
cf.dwEffects =CFE_PROTECTED;
cf.crTextColor =RGB(0,0,255);
_tcscpy(cf.szFaceName,_T("Courier New"));
m_richEdit.SetSel(lStart,lEnd);
m_richEdit.SetSelectionCharFormat(cf);
}
//m_richEdit.SetEventMask(m_richEdit.GetEventMask() | ENM_PROTECTED);
}
void CPaneEditorWnd::UpdateDocStatus()
{
CHARRANGE cr;
m_richEdit.LockWindowUpdate();
m_richEdit.GetSel(cr);
int i, nLines = m_richEdit.GetLineCount();
for(i=0;i<nLines;i++)
FormatLine(i);
m_richEdit.SetSel(cr);
m_richEdit.UnlockWindowUpdate();
}
/////////////////////////////////////////////////////////////////////////////
// CPaneEditorWnd message handlers
void CPaneEditorWnd::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
CWnd *pRichEd = GetDlgItem(IDC_RICHEDIT);
if(pRichEd!=NULL && pRichEd->GetSafeHwnd()!=NULL)
{
CRect rcClient, rcTemp;
GetClientRect(&rcClient);
pRichEd->MoveWindow(&rcClient);
}
}
void CPaneEditorWnd::OnUpdate()
{
m_richEdit.SetEventMask(m_richEdit.GetEventMask() &~ ENM_PROTECTED);
CHARFORMAT cf0,cf1;
ZeroMemory(&cf0,sizeof(cf0));
cf0.cbSize =sizeof(cf0);
cf0.dwMask =CFM_FACE|CFM_COLOR|CFM_PROTECTED;
cf0.dwEffects =CFE_PROTECTED;
cf0.crTextColor =RGB(0,0,0);
_tcscpy(cf0.szFaceName,_T("Courier New"));
ZeroMemory(&cf1,sizeof(cf1));
cf1.cbSize =sizeof(cf1);
cf1.dwMask =CFM_FACE|CFM_COLOR|CFM_PROTECTED;
cf1.dwEffects =CFE_PROTECTED;
cf1.crTextColor =RGB(0,0,255);
_tcscpy(cf1.szFaceName,_T("Courier New"));
m_richEdit.SetSel(0,-1);
m_richEdit.SetDefaultCharFormat(cf0);
m_richEdit.ReplaceSel("");
int i, nSize = m_pDoc->m_aRules.GetSize();
bool fOn = false;
for(i=0;i<nSize;i++)
{
const docElement& el = m_pDoc->m_aRules[i];
m_richEdit.SetSel(-1,-1);
m_richEdit.SetSelectionCharFormat(cf0);
m_richEdit.ReplaceSel(el.strLine);
m_richEdit.SetSel(-1,-1);
m_richEdit.SetSelectionCharFormat(cf0);
m_richEdit.ReplaceSel("\r\n");
FormatLine(i);
}
m_richEdit.SetEventMask(m_richEdit.GetEventMask() | ENM_PROTECTED);
m_fModified = false;
}
BOOL CPaneEditorWnd::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
OnUpdate();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CPaneEditorWnd::OnProtectedRichEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
ENPROTECTED *pEnProtected = reinterpret_cast<ENPROTECTED *>(pNMHDR);
// TODO: The control will not send this notification unless you override the
// CDialog::OnInitDialog() function to send the EM_SETEVENTMASK message
// to the control with the ENM_PROTECTED flag ORed into the lParam mask.
int nLine1 = m_richEdit.LineFromChar(pEnProtected->chrg.cpMin);
int nLine2 = (pEnProtected->chrg.cpMin==pEnProtected->chrg.cpMax)
?nLine1:m_richEdit.LineFromChar(pEnProtected->chrg.cpMax);
(*pResult) = 0;
// Character message?
if( pEnProtected->msg>=WM_KEYFIRST &&
pEnProtected->msg<=WM_KEYLAST)
{
if(pEnProtected->wParam==VK_BACK)
nLine1--;
if(m_nFmtMin==-1) m_nFmtMin=nLine1; else m_nFmtMin=(nLine1<m_nFmtMin)?nLine1:m_nFmtMin;
if(m_nFmtMax==-1) m_nFmtMax=nLine2+1; else m_nFmtMax=(nLine2>m_nFmtMax)?nLine2:m_nFmtMax;
KillTimer(ID_TIMER_UPDATEDOCSTATUS);
SetTimer(ID_TIMER_UPDATEDOCSTATUS,300,NULL);
m_pDoc->SetModifiedFlag();
}
}
void CPaneEditorWnd::OnCancel()
{
}
LRESULT CPaneEditorWnd::OnFormatLines(WPARAM wP, LPARAM lP)
{
if(wP==0 && lP==0)
{
if(m_nFmtMin==-1)
return 0;
wP = (m_nFmtMin<0)?0:(UINT)m_nFmtMin, lP = (m_nFmtMax<0)?0:(UINT)m_nFmtMax;
m_nFmtMin = -1, m_nFmtMax = -1;
}
int i;
CHARRANGE cr;
m_richEdit.SetEventMask(m_richEdit.GetEventMask() &~ ENM_PROTECTED);
m_richEdit.LockWindowUpdate();
m_richEdit.GetSel(cr);
for(i=(int)wP; i<=(int)lP; i++)
FormatLine(i);
m_richEdit.SetSel(cr);
m_richEdit.UnlockWindowUpdate();
m_richEdit.SetEventMask(m_richEdit.GetEventMask() | ENM_PROTECTED);
return 0;
}
void CPaneEditorWnd::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnTimer(nIDEvent);
if(nIDEvent==ID_TIMER_UPDATEDOCSTATUS)
{
OnFormatLines(0,0);
/*UpdateDocStatus();*/
KillTimer(ID_TIMER_UPDATEDOCSTATUS);
}
}
BOOL CPaneEditorWnd::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if(pMsg->message==WM_KEYDOWN)
return GetParentFrame()->PreTranslateMessage(pMsg);
return CDialog::PreTranslateMessage(pMsg);
}