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

📄 syneditview.cpp

📁 编译原理语法分析器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{
	m_nParseArraySize = 0;
	m_nHorzPos = 0;

	if(m_pdwParseCookies != NULL) {
		delete m_pdwParseCookies;
		m_pdwParseCookies = NULL;
	}

	if(m_pCacheBitmap!=NULL) {
		delete m_pCacheBitmap;
		m_pCacheBitmap = NULL;
	}
	
	return;
}


int CSynEditView::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	if (CSynEditView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	GetRichEditCtrl().HideSelection(TRUE, FALSE); 

	return 0;
}


void CSynEditView::CalcSelection()
{
	CRichEditCtrl &SynCtrl = GetRichEditCtrl();	
	CHARRANGE cr;
	SynCtrl.GetSel( cr ); 
	m_ptSelStart = SynCtrl.GetCharPos( cr.cpMin ); 
	m_ptSelEnd = SynCtrl.GetCharPos( cr.cpMax );
}

/*////////////////////////////////////////////////////
[函数]:	IsStrInSelection(int ptLeft, int ptTop)
[功能]	根据给定点的x,y坐标判断该点是否在选定区域内
[入口参数]:
	ptLeft	-	给定点的x位置
	ptTop	-	给定点的y位置
[返回值]:
	TRUE	-	该点在选定区域内
	FLASE	-	该点在在选定区域内
/*////////////////////////////////////////////////////
BOOL CSynEditView::IsStrInSelection(int ptLeft, int ptTop)
{
	if( m_ptSelStart == m_ptSelEnd ) //如果没有选定直接返回FALSE
		return FALSE;

	CPoint ptSelStart = m_ptSelStart;
	CPoint ptSelEnd = m_ptSelEnd;
	//考虑边界的情况,将选定区域左右延伸半个字符宽度
	ptSelStart.x -= m_nCharNumberWidth/2;
	ptSelEnd.x += m_nCharNumberWidth/2;

	if( ptSelStart.y == ptSelEnd.y ) { //如果选定行为单行
		if( ptTop != ptSelStart.y ) //如果光标不在该行
			return FALSE;
		else {
			if( ptLeft >= ptSelStart.x && ptLeft <= ptSelEnd.x)
				return TRUE;
			else
				return FALSE;
		}
	}
	else {
		if( ptTop == ptSelStart.y ) { //如果当前位置在选取定行的第一行
			if( ptLeft <  ptSelStart.x )
				return FALSE;
			else
				return TRUE;
		}
		if( ptTop == ptSelEnd.y ) { //如果当前位置在选定行的最后一行
			if( ptLeft < ptSelEnd.x )
				return TRUE;
			else
				return FALSE;
		}
		else if( ptTop > ptSelStart.y && ptTop < ptSelEnd.y ) //如果当前位置在选定行的中间
			return TRUE;
		else
			return FALSE;
	}
}

//判断给定的字符是否在选择区域内,并画出该字符串
void CSynEditView::JudgeInSeletioAndDrawText(CDC *cacheDC, CRect &rcLine, CString &str, COLORREF clrBkColor, COLORREF clrText)
{
	COLORREF clrSelText;

	int nFormat = DT_LEFT|DT_NOPREFIX|DT_EXPANDTABS|DT_VCENTER|DT_SINGLELINE|DT_RTLREADING;
	CSize size = cacheDC->GetTextExtent(str); 
	if( !IsSelectionInStr(rcLine.left, size.cx, rcLine.top) ) {
		BOOL bStrLeft = IsStrInSelection( rcLine.left, rcLine.top );
		BOOL bStrRight = IsStrInSelection( rcLine.left + size.cx, rcLine.top );
		
		if( !bStrLeft && !bStrRight ) { //如果str的左右都不在选定区域内			
			cacheDC->SetBkColor( clrBkColor ); 
			cacheDC->SetTextColor( clrText );
			cacheDC->TextOut( rcLine.left, rcLine.top, str);
			rcLine.OffsetRect( size.cx, 0 );
			return;
		}
		else if( bStrLeft && bStrRight ) { //如果str的左右都在选定区域内
			CRect rect(rcLine);
			rect.right = rect.left + size.cx;
			cacheDC->FillSolidRect( &rect, m_clrBKSelText ); 
			clrSelText = RGB( 255-GetRValue(clrText), 255-GetGValue(clrText), 255-GetBValue(clrText) );
			cacheDC->SetTextColor( clrSelText );
			cacheDC->TextOut( rcLine.left, rcLine.top, str);
			rcLine.OffsetRect( size.cx, 0 );
			return;
		}
	}
	//如果str部分在选定区域内, 或者选定区域在str内执行以下代码
	CString strChar;
	for( int nChar = 0; nChar < str.GetLength(); nChar++ ) {
		strChar = str.Mid( nChar, 1 );
		size = cacheDC->GetTextExtent( strChar ); 
		BOOL bStrLeft = IsStrInSelection( rcLine.left, rcLine.top );
		BOOL bStrRight = IsStrInSelection( rcLine.left + size.cx, rcLine.top );
		if( bStrLeft && bStrRight ) { 
			CRect rect(rcLine);
			rect.right = rect.left + size.cx;
			cacheDC->FillSolidRect( &rect, m_clrBKSelText ); 
			clrSelText = RGB( 255-GetRValue(clrText), 255-GetGValue(clrText), 255-GetBValue(clrText) );
			cacheDC->SetTextColor( clrSelText );
		}
		else {
			cacheDC->SetBkColor( clrBkColor ); 
			cacheDC->SetTextColor( clrText );
		}
		cacheDC->TextOut( rcLine.left, rcLine.top, strChar);
		rcLine.OffsetRect( size.cx, 0 );
	}
}

//计算水平滚动位置,以便在水平滚动时可以正确显示
void CSynEditView::CalcHorzScrollPos()
{
	if(m_nWordWrap == WrapToWindow)
	{
		m_nHorzPos = 0;
		return;
	}

	SCROLLINFO si;
	si.cbSize = sizeof(si);
	GetScrollInfo(SB_HORZ, &si);
	
	if( m_bTracking ) 
		m_nHorzPos = si.nTrackPos;
	else
		m_nHorzPos = si.nPos;
}

//在RichEditView上画出内容
void CSynEditView::DrawSynEditView()
{
	if(!m_bAllowDraw)
 		return;

  	CRichEditCtrl &SynCtrl = GetRichEditCtrl();
	m_nLineCount = SynCtrl.GetLineCount(); 
 	m_nCurrentLine = GetCurrentLine();

 	if (m_pdwParseCookies != NULL)
 	{
 		if (m_nParseArraySize != m_nLineCount)
 		{
			int nCurrentLine = m_nCurrentLine;
			if(m_nParseArraySize < m_nLineCount) 
			{
				nCurrentLine = m_nParseArraySize + m_nCurrentLine - m_nLineCount; 
				if(nCurrentLine<0)
					nCurrentLine = m_nCurrentLine;
			}
			if(m_nCurrentLine>m_nLineCount)
				nCurrentLine=0;
 			//	重新分配缓冲区大小
 			DWORD *pdwNewArray = new DWORD[m_nLineCount];
 			if (m_nCurrentLine > 0)
 				memcpy(pdwNewArray, m_pdwParseCookies, sizeof(DWORD) * nCurrentLine);
 			delete m_pdwParseCookies;
 			m_nParseArraySize = m_nLineCount;
 			m_pdwParseCookies = pdwNewArray;
			memset(m_pdwParseCookies + nCurrentLine, 0xff, sizeof(DWORD) * (m_nParseArraySize - nCurrentLine));
 		}
 	}
 	
 	CDC *pdc=GetDC();
 	CDC cacheDC;
 	VERIFY(cacheDC.CreateCompatibleDC(pdc));
 	if (m_pCacheBitmap == NULL)
 	{
 		m_pCacheBitmap = new CBitmap;
 		m_pCacheBitmap->CreateCompatibleBitmap(pdc, m_rcClient.Width(), m_rcClient.Height());  //nLineHeight);
 	}
 	CBitmap *pOldBitmap = cacheDC.SelectObject(m_pCacheBitmap);
 
	CalcSelection();
	CalcHorzScrollPos();

	CString str;
	int nLine = SynCtrl.GetFirstVisibleLine();
 	if(nLine==0)
		m_bRealReturn = TRUE;
	else
		m_bRealReturn = GetLineString(nLine-1, str);

	CRect rcEditor(m_rcClient);
	//将显示区域背景色画好
	cacheDC.FillSolidRect(&rcEditor, m_clrBkColor); 	

	rcEditor.left = m_nLeftMargin - m_nHorzPos - 1;
	int nLinesTop = GetLinesTop(nLine); //第一行要计算好偏移值,因为第一行可能只显示部分
	rcEditor.top = nLinesTop + m_nTopMargin;
	rcEditor.bottom = rcEditor.top + m_nLineHeight;	

	int nNumberToDraw = 0;
	while(rcEditor.top <= m_rcClient.bottom ) 
	{
		if(nLine > m_nLineCount-1)
			break;
		//画出一行文本
		DrawSingleLineColorText(&cacheDC, nLine++, rcEditor);
		//重新定位下一行的位置
		rcEditor.OffsetRect(0, m_nLineHeight );
	}

	//将缓冲画布cacheDC上的内容复制到RichEditView视上
	pdc->BitBlt(m_rcClient.left, m_rcClient.top, m_rcClient.Width(), m_rcClient.Height(), &cacheDC, 0, 0, SRCCOPY);
 	
 	cacheDC.SelectObject(pOldBitmap);
 	cacheDC.DeleteDC();	
}


/*////////////////////////////////////////////////////
[函数]:	IsSelectionInStr(int nFromHere, int nStrWidth, int nTop)
[功能]:	判断选择选区域是否在字符串所处位置的内部
[入口参数]:
	nFromHere	-	待测试的字符串的起始位置
	nStrWidth	-	待测试的字符串的宽度
	nTop		-	待测试的字符串的顶部位置
[返回值]:
	TRUE	-	选定区域在字符串所处位置的内部
	FLASE	-	选定区域不在字符串所处位置的内部
/*////////////////////////////////////////////////////
BOOL CSynEditView::IsSelectionInStr(int nFromHere, int nStrWidth, int nTop)
{
	if( m_ptSelStart == m_ptSelEnd )
		return FALSE;

	if( m_ptSelStart.y != m_ptSelEnd.y )  //如果选定行不为单行,返回,因为字符不可能跨行
		return FALSE;

	if( m_ptSelStart.y != nTop )  //如果待测试行的顶部不等于选定行的顶部则返回
		return FALSE;

	if( (m_ptSelStart.x > nFromHere) && (m_ptSelEnd.x < nFromHere + nStrWidth) )
		return TRUE;
	else
		return FALSE;
}


COLORREF CSynEditView::GetColor(int nColorIndex)
{
	switch(nColorIndex) 
	{
	case COLORINDEX_NUMBER:
		return m_clrNumberColor;
	case COLORINDEX_BK:
		return m_clrBkColor;
	case COLORINDEX_COMMENT:
		return m_clrCommentColor;
	case COLORINDEX_SYNTAX:
		return m_clrSyntaxColor;
	case COLORINDEX_NORMAL:
		return m_clrNormalColor;
	case COLORINDEX_STRING:
		return m_clrStringColor;
	case COLORINDEX_CHAR:
		return m_clrCharColor;
	default:
		return m_clrNormalColor;
	}
}

//这个函数的作用是在粘贴时重置nParseArraySize的语法解析缓冲区
void CSynEditView::SetParseCookieZeroFromGivenLine(int nParseArraySize)
{
	memset(m_pdwParseCookies + nParseArraySize, 0xff, sizeof(DWORD) * (m_nParseArraySize - nParseArraySize));
}


//语法解析相关函数,判断给定的串是否是当前是语言的语法关键字
BOOL CSynEditView::IsSynWord(CString &strReadyToTest)
{
	BOOL bCase, bMatch;

	//设定当前语言是否区分大小写
	switch(m_nLanguage) 
	{
	case _CPP:
		bCase = TRUE;
		break;
	case _BASIC:
		bCase = FALSE;
		break;
	default:
		bCase = FALSE;
	}

	for(int i=0; i<m_strArrayKeyWords.GetSize(); i++) 
	{
		CString str = m_strArrayKeyWords[i];
		if(bCase)
			bMatch = (strReadyToTest.Compare(m_strArrayKeyWords[i])==0);
		else 
			bMatch = (strReadyToTest.CompareNoCase(m_strArrayKeyWords[i])==0);

		if(bMatch)
			return TRUE;
	}
	return FALSE;
}

//语法解析相关函数,装入指定语言的语法关键字
void CSynEditView::LoadSynWord(INT nLanguage) 
{
	CString strAllSynWord;
	m_strArrayKeyWords.RemoveAll();
	
	switch (nLanguage) 
	{
	case _CPP:
		strAllSynWord = _T(" #define,#else,#elif,#elseif,#endif,#error,#if,#ifdef,#ifndef,#include,#pragma,#undef,__asm,__based,__cdecl,__declspec,__except,__fastcall,__finally,__inline,__int16,__int32,__int64,__int8,__leave,__multiple_inheritance,__pascal,__single_inheritance,__stdcall,__try,__uuidof,__virtual_inheritance,_asm,_cdecl,_fastcall,_pascal,_stdcall,afx_msg,auto,bool,break,case,catch,char,class,code_seg,const,const_cast,continue,default,defined,delete,dllexport,dllimport,do,double,dynamic_cast,else,enum,explicit,extern,false,float,for,friend,goto,if,inline,int,interface,long,main,mutable,naked,namespace,new,off,on,once,operator,pack,pascal,pop,private,protected,public,push,register,reinterpret_cast,return,short,signed,sizeof,static,static_cast,struct,switch,template,this,thread,throw,true,try,typedef,typeid,typename,union,unsigned,using,uuid,virtual,void,volatile,while,wmain,xalloc,");
		break;
	case _BASIC:
		strAllSynWord = _T(" Alias,And,Any,As,Base,Boolean,Byref,Byte,Byval,Call,Case,Close,Compare,Const,Currency,Data,Date,Declare,Defbool,Defbyte,Defcur,Defdate,Defdbl,Defdec,Defint,Deflng,Defobj,Defsng,Defstr,Defvar,Dim,Do,Double,Each,Else,Elseif,End,Enum,Eqv,Erase,Error,Event,Exit,Explicit,False,For,Function,Get,Global,Gosub,Goto,If,IIf,Imp,Implements,In,Integer,Is,Let,Lib,Line,Lock,Long,Loop,Lset,New,Next,Not,Object,On,Open,Option,Optional,Or,Preserve,Print,Private,Property,Public,Put,Raiseevent,Redim,Resume,Return,Rset,Select,Set,Single,Static,Stop,String,Sub,Then,To,True,Type,Ubound,Unload,Unlock,Variant,Wend,While,With,Write,Xor,");
		break;
	default: //纯文本
		strAllSynWord = _T("");
		return;
	}

	CString strTemp;
	int nPosPrior = 0;
	int nPos;	

	nPos = strAllSynWord.Find(_T(","), nPosPrior);
	while(nPos!=-1)
	{
		strTemp = strAllSynWord.Mid(nPosPrior+1 , nPos - nPosPrior - 1);
		m_strArrayKeyWords.Add(strTemp);
		
		nPosPrior = nPos;
		nPos = strAllSynWord.Find(_T(","),  nPosPrior + 1);			
	}
}


void CSynEditView::CalcEditorInfo()
{
	ShowWindow(FALSE);

	CPoint p1, p2;
	CRichEditCtrl &SynCtrl = GetRichEditCtrl();

	SynCtrl.SetWindowText(_T("8"));  
	p1 = SynCtrl.GetCharPos(0);
	p2 = SynCtrl.GetCharPos(1);
	m_nCharNumberWidth = p2.x - p1.x;	//数字宽度

	SynCtrl.SetWindowText(_T(" "));  
	p1 = SynCtrl.GetCharPos(0);
	p2 = SynCtrl.GetCharPos(1);
	m_nCharSpaceWidth = p2.x - p1.x;	//空格宽度
	
	SynCtrl.SetWindowText(_T("\t"));  
	p1 = SynCtrl.GetCharPos(0);	
	p2 = SynCtrl.GetCharPos(1);
	m_nCharTabWidth = p2.x - p1.x;	//TAB宽度

	SynCtrl.SetWindowText(_T("\n     "));
	CPoint ps, pe;
	p1 = SynCtrl.GetCharPos(0);
	p2 = SynCtrl.GetCharPos(3);
	//m_nLineHeight = p2.y - p1.y; //行高
	m_nLineHeight = 16;

	ShowWindow(TRUE);
}


LRESULT CSynEditView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch (message) 
	{
	case WM_PAINT:
		{
			CPaintDC dc(this); // device context for painting
			DrawSynEditView();
			return FALSE;
		}
	case WM_PASTE:
		{
			//处理粘贴的情况,当用户粘入rtf格式时,只取出其中的文本,否则直接粘可能会引起文本错位
			char * buffer;
			if(!OpenClipboard())
				return FALSE;	
			buffer = (char*)::GetClipboardData(CF_TEXT);
			CloseClipboard(); 
			CString str = buffer;
			
			CRichEditCtrl &edit = GetRichEditCtrl();
			CHARRANGE cr;
			edit.GetSel(cr); 	

			SetParseCookieZeroFromGivenLine(edit.LineFromChar(cr.cpMin)); //粘贴时需重置解析缓冲区
			edit.ReplaceSel(str, TRUE); 
			return FALSE;
		}
	case WM_SIZE:
		{			
			CSynEditView::WindowProc(message, wParam, lParam);			
			
			GetParent()->GetClientRect(&m_rcClient); 
			MoveWindow(&m_rcClient);

			if (m_pCacheBitmap != NULL)
			{
				delete m_pCacheBitmap;
				m_pCacheBitmap = NULL;
			}

			return FALSE;
		}
	default:
		return CSynEditView::WindowProc(message, wParam, lParam);
	}
}

void CSynEditView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{	
	InvalidateRect(m_rcClient, FALSE);
	m_bAllowDraw = FALSE;
	CSynEditView::OnHScroll(nSBCode, nPos, pScrollBar);
	m_bAllowDraw = TRUE;
	ValidateRect(m_rcClient);
	
	//判断用户是否正在拖动水平滚动条
	SCROLLINFO si;
	si.cbSize = sizeof(si);
	GetScrollInfo(SB_HORZ, &si);
	if(nSBCode==SB_THUMBPOSITION || nSBCode==SB_THUMBTRACK)
		m_bTracking = TRUE;
	else
		m_bTracking = FALSE;
	
	SendMessage(WM_PAINT, 0, 0);	
}

void CSynEditView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	InvalidateRect(m_rcClient, FALSE);
	m_bAllowDraw = FALSE;
	CSynEditView::OnVScroll(nSBCode, nPos, pScrollBar);
	m_bAllowDraw = TRUE;
	ValidateRect(m_rcClient);
	SendMessage(WM_PAINT, 0, 0);
}

/*//////////////////////////////////////////////////////////////////////////////////////
[函数]:ParseLine(m_strArrayKeyWords, dwCookie, strLine, ColorInfo, nActualItems) );

⌨️ 快捷键说明

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