Programming 版 (精华区)
发信人: SwordLea (飞刀李), 信区: Programming
标 题: Re: 怎样实现类似 UltraEdit的语法高亮
发信站: 哈工大紫丁香 (2004年03月26日13:52:06 星期五), 站内信件
没太看懂你的问题,是不是想自己实现CRichEdit的语法高亮显示啊?
我曾经找过一个SyntaxColorizer类,但在个别系统不太好用。
// SyntaxColorizer.h: interface for the CSyntaxColorizer class.
//
// Version: 1.0.1
// Author: Jeff Schering jeffschering@hotmail.com
// Date: Feb 22, 2001
// Copyright 2001 by Jeff Schering
//
// Changes in 1.0.1:
// 1. added UNICODE support
//////////////////////////////////////////////////////////////////////
#if
!defined(AFX_SYNTAXCOLORIZER_H__5C50E421_E4AC_11D4_A61E_60A459C10100__INCLUDED_
)
#define AFX_SYNTAXCOLORIZER_H__5C50E421_E4AC_11D4_A61E_60A459C10100__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define _UNICODE
#define CLR_STRING RGB(55,0,200)
#define CLR_PLAIN RGB(0,0,0)
#define CLR_COMMENT RGB(0,170,0)
#define CLR_KEYWORD RGB(0,0,255)
#define GRP_KEYWORD 0
#define TBLSIZE 65536
class CSyntaxColorizer
{
public:
CSyntaxColorizer();
virtual ~CSyntaxColorizer();
//protected vars
protected:
unsigned short *m_pTableZero, *m_pTableOne;
unsigned short *m_pTableTwo, *m_pTableThree;
unsigned short *m_pTableFour, *m_pAllowable;
enum Types
{
SKIP,
DQSTART, //Double Quotes start
DQEND, //Double Quotes end
SQSTART, //Single Quotes start
SQEND, //Single Quotes end
CMSTART, //Comment start (both single and multi line)
SLEND, //Single line comment end
MLEND, //Multi line comment end
KEYWORD //Keyword start
} m_type;
struct SKeyword
{
TCHAR* keyword;
int keylen;
CHARFORMAT cf;
int group;
SKeyword* pNext;
SKeyword() { pNext = NULL; }
};
SKeyword* m_pskKeyword;
CHARFORMAT m_cfComment;
CHARFORMAT m_cfString;
CHARFORMAT m_cfDefault;
//protected member functions
protected:
void addKey(LPCTSTR Keyword, CHARFORMAT cf, int grp);
void createTables();
void deleteTables();
void createDefaultKeywordList();
void createDefaultCharFormat();
void colorize(LPTSTR lpszBuf, CRichEditCtrl *pCtrl, long iOffset = 0);
//public member functions
public:
void Colorize(long StartChar, long nEndChar, CRichEditCtrl *pCtrl);
void Colorize(CHARRANGE cr, CRichEditCtrl *pCtrl);
void GetCommentStyle(CHARFORMAT &cf) { cf = m_cfComment; };
void GetStringStyle(CHARFORMAT &cf) { cf = m_cfString; };
void GetGroupStyle(int grp, CHARFORMAT &cf);
void GetDefaultStyle(CHARFORMAT &cf) { cf = m_cfDefault; };
void SetCommentStyle(CHARFORMAT cf) { m_cfComment = cf; };
void SetCommentColor(COLORREF cr);
void SetStringStyle(CHARFORMAT cf) { m_cfString = cf; };
void SetStringColor(COLORREF cr);
void SetGroupStyle(int grp, CHARFORMAT cf);
void SetGroupColor(int grp, COLORREF cr);
void SetDefaultStyle(CHARFORMAT cf) { m_cfDefault = cf; };
void AddKeyword(LPCTSTR Keyword, CHARFORMAT cf, int grp = 0);
void AddKeyword(LPCTSTR Keyword, COLORREF cr, int grp = 0);
void ClearKeywordList();
CString GetKeywordList();
CString GetKeywordList(int grp);
};
#endif //
!defined(AFX_SYNTAXCOLORIZER_H__5C50E421_E4AC_11D4_A61E_60A459C10100__INCLUDED_
)
// SyntaxColorizer.cpp: implementation of the CSyntaxColorizer class.
//
// Version: 1.0.1
// Author: Jeff Schering jeffschering@hotmail.com
// Date: Feb 22, 2001
// Copyright 2001 by Jeff Schering
//
// Changes in 1.0.1:
// 1. added UNICODE support
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SyntaxColorizer.h"
#define _UNICODE
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSyntaxColorizer::CSyntaxColorizer()
{
createDefaultCharFormat();
SetCommentColor(CLR_COMMENT);
SetStringColor(CLR_STRING);
createTables();
m_pskKeyword = NULL;
}
CSyntaxColorizer::~CSyntaxColorizer()
{
ClearKeywordList();
deleteTables();
}
//////////////////////////////////////////////////////////////////////
// Member Functions
//////////////////////////////////////////////////////////////////////
void CSyntaxColorizer::createDefaultCharFormat()
{
m_cfDefault.dwMask = CFM_CHARSET | CFM_FACE | CFM_SIZE | CFM_OFFSET |
CFM_COLOR;
m_cfDefault.dwMask ^= CFM_ITALIC ^ CFM_BOLD ^ CFM_STRIKEOUT ^
CFM_UNDERLINE;
m_cfDefault.dwEffects = 0;
m_cfDefault.yHeight = 200; //10pts * 20 twips/point = 200 twips
m_cfDefault.bCharSet = ANSI_CHARSET;
m_cfDefault.bPitchAndFamily = FIXED_PITCH | FF_MODERN;
m_cfDefault.yOffset = 0;
m_cfDefault.crTextColor = CLR_PLAIN;
_tcscpy(m_cfDefault.szFaceName,"Courier New");
m_cfDefault.cbSize = sizeof(m_cfDefault);
m_cfComment = m_cfDefault;
m_cfString = m_cfDefault;
}
void CSyntaxColorizer::createDefaultKeywordList()
{
LPTSTR sKeywords = _T("__asm,else,main,struct,__assume,enum,"
"__multiple_inheritance,switch,auto,__except,__single_inheritance,"
"template,__based,explicit,__virtual_inheritance,this,bool,extern,"
"mutable,thread,break,false,naked,throw,case,__fastcall,namespace,"
"true,catch,__finally,new,try,__cdecl,float,noreturn,__try,char,for,"
"operator,typedef,class,friend,private,typeid,const,goto,protected,"
"typename,const_cast,if,public,union,continue,inline,register,"
"unsigned,__declspec,__inline,reinterpret_cast,using,declaration,"
"directive,default,int,return,uuid,delete,__int8,short,"
"__uuidof,dllexport,__int16,signed,virtual,dllimport,__int32,sizeof,"
"void,do,__int64,static,volatile,double,__leave,static_cast,wmain,"
"dynamic_cast,long,__stdcall,while");
LPTSTR sDirectives = _T("#define,#elif,#else,#endif,#error,#ifdef,"
"#ifndef,#import,#include,#line,#pragma,#undef");
LPTSTR sPragmas = _T("alloc_text,comment,init_seg1,optimize,auto_inline,"
"component,inline_depth,pack,bss_seg,data_seg,"
"inline_recursion,pointers_to_members1,check_stack,"
"function,intrinsic,setlocale,code_seg,hdrstop,message,"
"vtordisp1,const_seg,include_alias,once,warning");
AddKeyword(sKeywords,CLR_KEYWORD,GRP_KEYWORD);
AddKeyword(sDirectives,CLR_KEYWORD,GRP_KEYWORD);
AddKeyword(sPragmas,CLR_KEYWORD,GRP_KEYWORD);
}
void CSyntaxColorizer::createTables()
{
m_pTableZero = new unsigned short[TBLSIZE]; m_pTableOne = new unsigned
short[TBLSIZE];
m_pTableTwo = new unsigned short[TBLSIZE]; m_pTableThree = new unsigned
short[TBLSIZE];
m_pTableFour = new unsigned short[TBLSIZE]; m_pAllowable = new unsigned
short[TBLSIZE];
memset(m_pTableZero,SKIP,TBLSIZE); memset(m_pTableOne,SKIP,TBLSIZE);
memset(m_pTableTwo,SKIP,TBLSIZE); memset(m_pTableThree,SKIP,TBLSIZE);
memset(m_pTableFour,SKIP,TBLSIZE); memset(m_pAllowable,false,TBLSIZE);
*(m_pTableZero + _T('"')) = DQSTART; *(m_pTableZero + _T('\'')) =
SQSTART;
*(m_pTableZero + _T('/')) = CMSTART; *(m_pTableOne + _T('"')) = DQEND;
*(m_pTableTwo + _T('\'')) = SQEND; *(m_pTableThree + _T('\n')) = SLEND;
*(m_pTableFour + _T('*')) = MLEND;
*(m_pAllowable + _T('\n')) = true; *(m_pAllowable + _T('\r')) = true;
*(m_pAllowable + _T('\t')) = true; *(m_pAllowable + _T('\0')) = true;
*(m_pAllowable + _T(' ')) = true; *(m_pAllowable + _T(';')) = true;
*(m_pAllowable + _T('(')) = true; *(m_pAllowable + _T(')')) = true;
*(m_pAllowable + _T('{')) = true; *(m_pAllowable + _T('}')) = true;
*(m_pAllowable + _T('[')) = true; *(m_pAllowable + _T(']')) = true;
*(m_pAllowable + _T('*')) = true;
}
void CSyntaxColorizer::deleteTables()
{
delete m_pTableZero; delete m_pTableOne; delete m_pTableTwo;
delete m_pTableThree; delete m_pTableFour; delete m_pAllowable;
}
void CSyntaxColorizer::AddKeyword(LPCTSTR Keyword, COLORREF cr, int grp)
{
LPTSTR token;
//make a copy of Keyword so that _tcstok will operate correctly
LPTSTR keyword = new TCHAR[_tcslen(Keyword) + 1];
_tcscpy(keyword,Keyword);
CHARFORMAT cf = m_cfDefault;
cf.crTextColor = cr;
token = _tcstok(keyword,_T(","));
while(token != NULL)
{
if(_tcsicmp(token,_T("rem")) == 0)
*(m_pTableTwo + _T('\n')) = SLEND; //set single quote as comment
start
addKey(token,cf,grp);
token = _tcstok(NULL,_T(","));
}
delete keyword;
}
void CSyntaxColorizer::AddKeyword(LPCTSTR Keyword, CHARFORMAT cf, int grp)
{
LPTSTR token;
//make a copy of Keyword so that _tcstok will operate correctly
LPTSTR keyword = new TCHAR[_tcslen(Keyword) + 1];
_tcscpy(keyword,Keyword);
token = _tcstok(keyword,_T(","));
while(token != NULL)
{
if(_tcsicmp(token,_T("rem")) == 0)
*(m_pTableTwo + _T('\n')) = SLEND; //set single quote as comment
start
addKey(token,cf,grp);
token = _tcstok(NULL,_T(","));
}
delete keyword;
}
void CSyntaxColorizer::addKey(LPCTSTR Keyword, CHARFORMAT cf, int grp) //add
in ascending order
{
SKeyword* pskNewKey = new SKeyword;
SKeyword* prev,*curr;
//the string pointed to by Keyword is only temporary, so make a copy
// of it for our list
pskNewKey->keyword = new TCHAR[_tcslen(Keyword)+1];
_tcscpy(pskNewKey->keyword,Keyword);
pskNewKey->keylen = _tcslen(Keyword);
pskNewKey->cf = cf;
pskNewKey->group = grp;
pskNewKey->pNext = NULL;
*(m_pTableZero + pskNewKey->keyword[0]) = KEYWORD;
//if list is empty, add first node
if(m_pskKeyword == NULL)
m_pskKeyword = pskNewKey;
else
{
//check to see if new node goes before first node
if(_tcscmp(Keyword,m_pskKeyword->keyword) < 0)
{
pskNewKey->pNext = m_pskKeyword;
m_pskKeyword = pskNewKey;
}
//check to see if new keyword already exists at the first node
else if(_tcscmp(Keyword,m_pskKeyword->keyword) == 0)
{
//the keyword exists, so replace the existing with the new
pskNewKey->pNext = m_pskKeyword->pNext;
delete m_pskKeyword->keyword; delete m_pskKeyword;
m_pskKeyword = pskNewKey;
}
else
{
prev = m_pskKeyword;
curr = m_pskKeyword->pNext;
while(curr != NULL && _tcscmp(curr->keyword,Keyword) < 0)
{
prev = curr;
curr = curr->pNext;
}
if(curr != NULL && _tcscmp(curr->keyword,Keyword) == 0)
{
//the keyword exists, so replace the existing with the new
prev->pNext = pskNewKey;
pskNewKey->pNext = curr->pNext;
delete curr->keyword; delete curr;
}
else
{
pskNewKey->pNext = curr;
prev->pNext = pskNewKey;
}
}
}
}
void CSyntaxColorizer::ClearKeywordList()
{
SKeyword* pTemp = m_pskKeyword;
while(m_pskKeyword != NULL)
{
*(m_pTableZero + m_pskKeyword->keyword[0]) = SKIP;
if(_tcsicmp(m_pskKeyword->keyword,_T("rem")) == 0)
*(m_pTableTwo + _T('\n')) = SKIP;
pTemp = m_pskKeyword->pNext;
delete m_pskKeyword->keyword;
delete m_pskKeyword;
m_pskKeyword = pTemp;
}
}
CString CSyntaxColorizer::GetKeywordList()
{
CString sList;
SKeyword* pTemp = m_pskKeyword;
while(pTemp != NULL)
{
sList += pTemp->keyword;
sList += _T(",");
pTemp = pTemp->pNext;
}
sList.TrimRight(_T(','));
return sList;
}
CString CSyntaxColorizer::GetKeywordList(int grp)
{
CString sList;
SKeyword* pTemp = m_pskKeyword;
while(pTemp != NULL)
{
if(pTemp->group == grp)
{
sList += pTemp->keyword;
sList += _T(",");
}
pTemp = pTemp->pNext;
}
sList.TrimRight(_T(','));
return sList;
}
void CSyntaxColorizer::SetCommentColor(COLORREF cr)
{
CHARFORMAT cf = m_cfComment;
cf.dwMask = CFM_COLOR;
cf.crTextColor = cr;
SetCommentStyle(cf);
}
void CSyntaxColorizer::SetStringColor(COLORREF cr)
{
CHARFORMAT cf = m_cfString;
cf.dwMask = CFM_COLOR;
cf.crTextColor = cr;
SetStringStyle(cf);
}
void CSyntaxColorizer::SetGroupStyle(int grp, CHARFORMAT cf)
{
SKeyword* pTemp = m_pskKeyword;
while(pTemp != NULL)
{
if(pTemp->group == grp)
{
pTemp->cf = cf;
}
pTemp = pTemp->pNext;
}
}
void CSyntaxColorizer::GetGroupStyle(int grp, CHARFORMAT &cf)
{
SKeyword* pTemp = m_pskKeyword;
while(pTemp != NULL)
{
if(pTemp->group == grp)
{
cf = pTemp->cf;
pTemp = NULL;
}
else
{
pTemp = pTemp->pNext;
//if grp is not found, return default style
if(pTemp == NULL) cf = m_cfDefault;
}
}
}
void CSyntaxColorizer::SetGroupColor(int grp, COLORREF cr)
{
CHARFORMAT cf;
GetGroupStyle(grp,cf);
cf.dwMask = CFM_COLOR;
cf.crTextColor = cr;
SetGroupStyle(grp,cf);
}
void CSyntaxColorizer::Colorize(CHARRANGE cr, CRichEditCtrl *pCtrl)
{
long nTextLength = 0;
if(cr.cpMin == 0 && cr.cpMax == -1) //send entire text of rich edit box
{
//set up the buffer to hold the text from the rich edit box
nTextLength = pCtrl->GetTextLength();
//if there is alot of text in the Rich Edit (>64K) then GetWindowText
doesn't
//work. We have to select all of the text, and then use GetSelText
pCtrl->SetSel(0,-1);
}
else
{
//set up the buffer to hold the text
nTextLength = cr.cpMax - cr.cpMin + 1;//add 1 because zero-based array
//get the text
pCtrl->SetSel(cr.cpMin,cr.cpMax);
}
LPTSTR lpszBuf = new TCHAR[nTextLength+1];
pCtrl->GetSelText(lpszBuf);
pCtrl->SetSelectionCharFormat(m_cfDefault);
colorize(lpszBuf,pCtrl,cr.cpMin);
delete lpszBuf;
}
void CSyntaxColorizer::Colorize(long nStartChar, long nEndChar, CRichEditCtrl
*pCtrl)
{
long nTextLength = 0;
if(nStartChar == 0 && nEndChar == -1) //send entire text of rich edit box
{
nTextLength = pCtrl->GetTextLength();
//if there is alot of text in the Rich Edit (>64K) then GetWindowText
doesn't
//work. We have to select all of the text, and then use GetSelText
pCtrl->SetSel(0,-1);
}
else
{
//set up the text buffer; add 1 because zero-based array
nTextLength = nEndChar - nStartChar + 1;
pCtrl->SetSel(nStartChar,nEndChar);
}
LPTSTR lpszBuf = new TCHAR[nTextLength+1];
pCtrl->GetSelText(lpszBuf);
pCtrl->SetSelectionCharFormat(m_cfDefault);
colorize(lpszBuf,pCtrl,nStartChar);
delete lpszBuf;
}
void CSyntaxColorizer::colorize(LPTSTR lpszBuf, CRichEditCtrl *pCtrl, long
iOffset /*=0*/)
{
//setup some vars
CHARFORMAT cf;
LPTSTR lpszTemp;
long iStart;
long x = 0;
SKeyword* pskTemp = m_pskKeyword;
unsigned short* pTable = m_pTableZero;
//do the work
while(lpszBuf[x])
{
switch(pTable[lpszBuf[x]])
{
case DQSTART:
pTable = m_pTableOne;
iStart = iOffset + x;
break;
case SQSTART:
pTable = m_pTableTwo;
iStart = iOffset + x;
break;
case CMSTART:
if(lpszBuf[x+1] == _T('/'))
{
pTable = m_pTableThree;
iStart = iOffset + x;
x++;
}
else if(lpszBuf[x+1] == _T('*'))
{
pTable = m_pTableFour;
iStart = iOffset + x;
x++;
}
else if(lpszBuf[x] == _T('\''))
{
pTable = m_pTableThree;
iStart = iOffset + x;
x++;
}
break;
case MLEND:
if(lpszBuf[x+1] == _T('/'))
{
x++;
pTable = m_pTableZero;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(m_cfComment);
}
break;
case SLEND:
if(lpszBuf[x-2] != _T('\\')) // line continuation character
{
pTable = m_pTableZero;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(m_cfComment);
}
break;
case DQEND:
pTable = m_pTableZero;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(m_cfString);
break;
case SQEND:
if(lpszBuf[x-1] == _T('\\') && lpszBuf[x+1] == _T('\''))
break;
pTable = m_pTableZero;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(m_cfString);
break;
case KEYWORD:
lpszTemp = lpszBuf+x;
while(pskTemp != NULL)
{
if(pskTemp->keyword[0] == lpszTemp[0])
{
int x1=0,y1=0;iStart = iOffset + x;
while(pskTemp->keyword[x1])
{
y1 += lpszTemp[x1] ^ pskTemp->keyword[x1];
x1++;
}
if(y1 == 0 && (*(m_pAllowable + (lpszBuf[x-1])) &&
*(m_pAllowable + (lpszBuf[x+pskTemp->keylen]))))
{
if(_tcsicmp(pskTemp->keyword,_T("rem")) == 0)
{
pTable = m_pTableThree;
}
else
{
x += pskTemp->keylen;
pCtrl->SetSel(iStart,iOffset + x);
pCtrl->SetSelectionCharFormat(pskTemp->cf);
}
}
}
pskTemp = pskTemp->pNext;
}
pskTemp = m_pskKeyword;
break;
case SKIP:;
}
x++;
}
//sometimes we get to the end of the file before the end of the string
//or comment, so we deal with that situation here
if(pTable == m_pTableOne)
{
cf = m_cfString;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(cf);
}
else if(pTable == m_pTableTwo)
{
cf = m_cfString;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(cf);
}
else if(pTable == m_pTableThree)
{
cf = m_cfComment;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(cf);
}
else if(pTable == m_pTableFour)
{
cf = m_cfComment;
pCtrl->SetSel(iStart,iOffset + x+1);
pCtrl->SetSelectionCharFormat(cf);
}
}
【
在
traceroute ( 懵懂书童∷苏格拉底最后的门徒) 的大作中提到: 】: 【 以下文字转载自
C_and_CPP 讨论区 】 : 【 原文由 traceroute 所发表 】
: 请问怎样设置UltraEdit,使编辑时文本采用C语言形式?
: 另外如何设置不同类型变量的颜色?setcolour好像不行
--
穿好一双鞋,以后用什么武器都不用再担心鞋子的问题
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.246.241]
※ 修改:·SwordLea 於 03月26日13:52:32 修改本文·[FROM: 202.118.246.241]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:211.354毫秒