⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alxsyntaxeditctrl.cpp

📁 一个不错的简单实用的公式解析器
💻 CPP
字号:
// ALXSyntaxEditCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "ALXSyntaxEditCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// Function list

extern ALXPRS_DEF_FUNCTION alxFunList[];
extern alxFuncCount;

/////////////////////////////////////////////////////////////////////////////
// Helper functions

BOOL alxIsLogicOprExpr(LPCSTR szExpr)
{
	short nOprID;
	int nOprPrioritet;

	return alxIsLogicOprExpr(szExpr, nOprID, nOprPrioritet);
}

/////////////////////////////////////////////////////////////////////////////
// CALXSyntaxEditCtrl

CALXSyntaxEditCtrl::CALXSyntaxEditCtrl()
{
	m_alxFunList = alxFunList;
	m_alxFuncCount = alxFuncCount;

	m_bInForcedChange = FALSE;

	m_nPrevLine = 0;

	memset(&m_cfDefault, 0, sizeof(m_cfDefault));
	m_cfDefault.cbSize = sizeof(m_cfDefault);
	m_cfDefault.dwEffects = CFE_PROTECTED; 
	m_cfDefault.dwMask = CFM_FACE | CFM_SIZE | CFM_PROTECTED | CFM_COLOR;
	m_cfDefault.yHeight = 200;
//	m_cfDefault.crTextColor = RGB(0,0, 255);
	strcpy(m_cfDefault.szFaceName, _T("Courier New")); 
}

CALXSyntaxEditCtrl::~CALXSyntaxEditCtrl()
{
}


BEGIN_MESSAGE_MAP(CALXSyntaxEditCtrl, CRichEditCtrl)
	//{{AFX_MSG_MAP(CALXSyntaxEditCtrl)
	ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
	//}}AFX_MSG_MAP
	ON_NOTIFY_REFLECT(EN_PROTECTED, OnProtected)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CALXSyntaxEditCtrl message handlers

void CALXSyntaxEditCtrl::OnChange() 
{
	CHARRANGE cr;

	SetRedraw(FALSE);

	GetSel(cr);

	CString str;
	str.Format("Min = %d, Max = %d\n",cr.cpMin,cr.cpMax);
	TRACE(str);

	int nCurLineStart, nCurLineEnd;
	// get first select line
	nCurLineStart = LineFromChar(cr.cpMin);
	// get last select line
	nCurLineEnd = cr.cpMax >= 0 ? LineFromChar(cr.cpMax) : max(0, GetLineCount() - 1);

	int nFirstLine, nLastLine;	// colorize line range 
	if(GetStyle() & ES_AUTOHSCROLL)
	{
		nFirstLine = min(m_nPrevLine, nCurLineStart);
		nLastLine = max(0,min(max(m_nPrevLine, nCurLineEnd), GetLineCount() - 1));

		for(int nLine = nFirstLine; nLine <= nLastLine; nLine++)
		{
			CString strLineText;
			int nFirstLineChar = LineIndex(nLine);
			int nLen = LineLength(nFirstLineChar);

			GetLine(nLine, strLineText.GetBuffer(nLen+2));
			strLineText.ReleaseBuffer();

			//call the colorizer
			Colorize(strLineText, nFirstLineChar);
		}
	}
	else // colorize all
	{
		nFirstLine = 0;
		nLastLine = max(0, GetLineCount() - 1);

		SetSel(0, -1); // select all
		CString strText = GetSelText();

		//call the colorizer
		Colorize(strText, 0);
	}

/*
	// test
	int nStart	= LineIndex(nFirstLine);
	int nEnd	= LineIndex(nLastLine) + LineLength(LineIndex(nLastLine));

	SetSel(nStart, nEnd);

	SetDefaultCharFormat(m_cfDefault);
	SetFormatRange(0, -1, m_cfDefault.crTextColor);
	SetFormatRange(nStart, nEnd, TXT_CLR_ERROR);
*/
	SetSel(cr);

	SetRedraw(TRUE);

	if(GetLineCount() > 1)
	{
		CRect rcInvalid;
		GetClientRect(rcInvalid);
		rcInvalid.top = GetCharPos(LineIndex(nFirstLine)).y;
		int nHeightLine = GetCharPos(LineIndex(1)).y - GetCharPos(LineIndex(0)).y;
		rcInvalid.bottom = rcInvalid.top + (nLastLine - nFirstLine + 1) * nHeightLine;

		InvalidateRect(rcInvalid,FALSE);
	}
	else
		Invalidate(FALSE);
}

void CALXSyntaxEditCtrl::Init()
{
	SetDefaultCharFormat(m_cfDefault);
	SetEventMask(GetEventMask() | ENM_CHANGE | ENM_PROTECTED);
}

void CALXSyntaxEditCtrl::Colorize(LPCSTR lpszBuf, int iOffset)
{
	int iStart;
	int i = 0;

	//do the work
	while(lpszBuf[i] != '\0')
	{
		switch(lpszBuf[i])
		{
		case '\r': case '\n':
			break;
		case '\0':
			continue;
		case '(':
			{
			iStart = (i++);
			LPCSTR lpszTemp = &lpszBuf[i];
			int nLevel = 0;
			while(*lpszTemp != '\0' && *lpszTemp != '\r' && *lpszTemp != '\n')
			{
				if(*lpszTemp == ')')
					if(nLevel == 0)
						break;
					else
						nLevel--;
				else if(*lpszTemp == '(')
					nLevel++;

				lpszTemp++;
			}

			if(*lpszTemp != ')' ||  nLevel != 0)
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);
			else
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_DEFAULT);

			continue;
			}
		case ')':
			{
			LPCSTR lpszTemp = &lpszBuf[i-1];
			iStart = (i++);
			int nLevel = 0;
			while(lpszTemp != lpszBuf && *lpszTemp != '\r' && *lpszTemp != '\n')
			{
				if(*lpszTemp == '(')
					if(nLevel == 0)
						break;
					else
						nLevel--;
				else if(*lpszTemp == ')')
					nLevel++;

				lpszTemp--;
			}

			if(*lpszTemp != '(' ||  nLevel != 0)
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);
			else
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_DEFAULT);

			continue;
			}
		case '"':
			iStart = (i++);
			while(lpszBuf[i] != '"' && lpszBuf[i] != '\0' && lpszBuf[i] != '\r' && lpszBuf[i] != '\n')
				i++;
			if(lpszBuf[i] == '"')
			{
				i++;
				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_STRING);
			}
			else
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);

			continue;
		case '\'':
			iStart = (i++);
			while(lpszBuf[i] != '\'' && lpszBuf[i] != '\0' && lpszBuf[i] != '\r' && lpszBuf[i] != '\n')
				i++;
			if(lpszBuf[i] == '\'')
			{
				i++;
				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_STRING);
			}
			else
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);

			continue;
		case '{':
			iStart = (i++);
			while(lpszBuf[i] != '{' && lpszBuf[i] != '}' && lpszBuf[i] != '\0' && lpszBuf[i] != '\r' && lpszBuf[i] != '\n')
				i++;
			if(lpszBuf[i] == '}')
			{
				i++;
				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_DATE);
			}
			else
				SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);

			continue;
		case '}':
			iStart = (i++);
			SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);
			continue;
		case '.':
			iStart = (i++);
			if(lpszBuf[i] >= '0' && lpszBuf[i] <= '9')
			{
				while(lpszBuf[i] >= '0' && lpszBuf[i] <= '9')
					i++;

				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_NUM);

				continue;
			}
			else if((lpszBuf[i] >= 'A' && lpszBuf[i] <= 'Z') || (lpszBuf[i] >= 'a' && lpszBuf[i] <= 'z'))
			{
				i++;
				while((lpszBuf[i] >= 'A' && lpszBuf[i] <= 'Z') || (lpszBuf[i] >= 'a' && lpszBuf[i] <= 'z'))
					i++;

				if(lpszBuf[i] == '.')
				{
					int nLen = i - iStart - 1;
					LPSTR lpszTemp = new CHAR[nLen + 1];
					memcpy(lpszTemp, &lpszBuf[iStart + 1], nLen); lpszTemp[nLen] = '\0';

					if(alxIsBoolExpr(lpszTemp))
					{
						i++;
						SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_BOOL);
					}
					else if(alxIsLogicOprExpr(lpszTemp))
					{
						i++;
						SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_LOGIC_OPR);
					}

					delete[] lpszTemp;
				}
				else
				{
					SetFormatRange(iStart+iOffset,iStart+iOffset+1, TXT_CLR_ERROR);
					i++;
					SetFormatRange(iStart+iOffset+1,i+iOffset, TXT_CLR_DEFAULT);
				}

			}
			else
				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_ERROR);

			continue;
		default:
			// function, variable or operator
			if((lpszBuf[i] >= 'a' && lpszBuf[i] <= 'z') || (lpszBuf[i] >= 'A' && lpszBuf[i] <= 'Z') || lpszBuf[i] == '_')
			{
				iStart = (i++);
				while((lpszBuf[i] >= 'a' && lpszBuf[i] <= 'z') || (lpszBuf[i] >= 'A' && lpszBuf[i] <= 'Z') || (lpszBuf[i] >= '0' && lpszBuf[i] <= '9') || lpszBuf[i] == '_')
					i++;

				int j = 0;
				int comlen = max(4,i-iStart);

				LPSTR szTmp = new CHAR[i-iStart+1];
				strncpy(szTmp, lpszBuf + iStart, i-iStart);
				szTmp[i-iStart] = '\0';

				// function
				if(lpszBuf[i] == '(')
				{
					// touch functions
					while(j < alxFuncCount)
					{
						// if it is that function
						if(_strnicmp(m_alxFunList[j].m_szName, szTmp, comlen) == 0)
						{
							SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_FUNCTION);
							break;
						}
						j++;
					}

					if(j == alxFuncCount) // if not found
					{
						if(alxIsLogicOprExpr(szTmp))
							SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_LOGIC_OPR);
						else
							SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_DEFAULT);
					}
				}
				else if(alxIsLogicOprExpr(szTmp))
					SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_LOGIC_OPR);
				else
					SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_DEFAULT);

				delete[] szTmp;

				continue;
			}
			else if(lpszBuf[i] >= '0' && lpszBuf[i] <= '9')
			{
				iStart = (i++);
				BOOL bDot = FALSE;
				while(lpszBuf[i] >= '0' && lpszBuf[i] <= '9' || lpszBuf[i] == '.')
				{
					if(lpszBuf[i] == '.')
						if(bDot)
							break;
						else
							bDot = TRUE;
					i++;
				}
				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_NUM);
				continue;
			}
			else
			{
				iStart = (i++);
				SetFormatRange(iStart+iOffset,i+iOffset, TXT_CLR_DEFAULT);
				continue;
			}

		}
		i++;
	}
}

void CALXSyntaxEditCtrl::SetFormatRange(int nStart, int nEnd, COLORREF clr)
{
	SetSel(nStart, nEnd);

	CHARFORMAT cfm;
	cfm.cbSize = sizeof(cfm);
    GetSelectionCharFormat(cfm);
	cfm.dwMask |= CFM_COLOR;
	cfm.crTextColor = clr;
	SetSelectionCharFormat(cfm);
	
/*	CString strTrace;
	strTrace.Format("Start = %d, End = %d \n",nStart, nEnd);
	TRACE(strTrace);
*/
//	if(cfm.crTextColor != clr)
//	{
//		cfm.crTextColor = clr;
//		SetSelectionCharFormat(cfm);
//	}
}

void CALXSyntaxEditCtrl::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
{
	CHARRANGE cr;
	GetSel(cr);
	// get first select line
	m_nPrevLine = LineFromChar(cr.cpMin);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -