SyntaxColorizer.cpp
Upload User: kairuinn
Upload Date: 2009-02-07
Package Size: 2922k
Code Size: 14k
Category:

Graph program

Development Platform:

Visual C++

  1. // SyntaxColorizer.cpp: implementation of the CSyntaxColorizer class.
  2. //
  3. // Version: 1.0.0
  4. // Author: Jeff Schering jeffschering@hotmail.com
  5. // Date: Jan 2001
  6. // Copyright 2001 by Jeff Schering
  7. //
  8. //////////////////////////////////////////////////////////////////////
  9. #include "stdafx.h"
  10. #include "SyntaxColorizer.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[]=__FILE__;
  14. #define new DEBUG_NEW
  15. #endif
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. CSyntaxColorizer::CSyntaxColorizer()
  20. {
  21. createDefaultCharFormat();
  22. SetCommentColor(CLR_COMMENT);
  23. SetStringColor(CLR_STRING);
  24. createTables();
  25. m_pskKeyword = NULL;
  26. createDefaultKeywordList();
  27. }
  28. CSyntaxColorizer::~CSyntaxColorizer()
  29. {
  30. //Bug fix by e-yes, applied by HOMO_PROGRAMMATIS <homo_programmatis@rt.mipt.ru>
  31. //ClearKeywordList() contains operation on tables - it causes errors
  32. //old code
  33. /**/ //deleteTables();
  34. /**/ //ClearKeywordList();
  35. //new code
  36. /**/ ClearKeywordList();
  37. /**/ deleteTables();
  38. //end of changes by HOMO_PROGRAMMATIS
  39. }
  40. //////////////////////////////////////////////////////////////////////
  41. // Member Functions
  42. //////////////////////////////////////////////////////////////////////
  43. void CSyntaxColorizer::createDefaultCharFormat()
  44. {
  45. m_cfDefault.dwMask = CFM_CHARSET | CFM_FACE | CFM_SIZE | CFM_OFFSET | CFM_COLOR;
  46. m_cfDefault.dwMask ^= CFM_ITALIC ^ CFM_BOLD ^ CFM_STRIKEOUT ^ CFM_UNDERLINE;
  47. m_cfDefault.dwEffects = 0;
  48. m_cfDefault.yHeight = 160; //10pts * 20 twips/point = 200 twips
  49. m_cfDefault.bCharSet = ANSI_CHARSET;
  50. m_cfDefault.bPitchAndFamily = FIXED_PITCH | FF_MODERN;
  51. m_cfDefault.yOffset = 0;
  52. m_cfDefault.crTextColor = CLR_PLAIN;
  53. strcpy(m_cfDefault.szFaceName,"Courier New");
  54. m_cfDefault.cbSize = sizeof(m_cfDefault);
  55. m_cfComment = m_cfDefault;
  56. m_cfString = m_cfDefault;
  57. }
  58. void CSyntaxColorizer::createDefaultKeywordList()
  59. {
  60. LPTSTR sKeywords = "__asm,else,main,struct,__assume,enum,"
  61. "__multiple_inheritance,switch,auto,__except,__single_inheritance,"
  62. "template,__based,explicit,__virtual_inheritance,this,bool,extern,"
  63. "mutable,thread,break,false,naked,throw,case,__fastcall,namespace,"
  64. "true,catch,__finally,new,try,__cdecl,float,noreturn,__try,char,for,"
  65. "operator,typedef,class,friend,private,typeid,const,goto,protected,"
  66. "typename,const_cast,if,public,union,continue,inline,register,"
  67. "unsigned,__declspec,__inline,reinterpret_cast,using,declaration,"
  68. "directive,default,int,return,uuid,delete,__int8,short,"
  69. "__uuidof,dllexport,__int16,signed,virtual,dllimport,__int32,sizeof,"
  70. "void,do,__int64,static,volatile,double,__leave,static_cast,wmain,"
  71. "dynamic_cast,long,__stdcall,while";
  72. LPTSTR sDirectives = "#define,#elif,#else,#endif,#error,#ifdef,"
  73. "#ifndef,#import,#include,#line,#pragma,#undef";
  74. LPTSTR sPragmas = "alloc_text,comment,init_seg1,optimize,auto_inline,"
  75. "component,inline_depth,pack,bss_seg,data_seg,"
  76. "inline_recursion,pointers_to_members1,check_stack,"
  77. "function,intrinsic,setlocale,code_seg,hdrstop,message,"
  78. "vtordisp1,const_seg,include_alias,once,warning"; 
  79. AddKeyword(sKeywords,CLR_KEYWORD,GRP_KEYWORD);
  80. AddKeyword(sDirectives,CLR_KEYWORD,GRP_KEYWORD);
  81. AddKeyword(sPragmas,CLR_KEYWORD,GRP_KEYWORD);
  82. }
  83. void CSyntaxColorizer::createTables()
  84. {
  85. m_pTableZero = new unsigned char[256]; m_pTableOne   = new unsigned char[256];
  86. m_pTableTwo  = new unsigned char[256]; m_pTableThree = new unsigned char[256];
  87. m_pTableFour = new unsigned char[256]; m_pAllowable  = new unsigned char[256];
  88. memset(m_pTableZero,SKIP,256); memset(m_pTableOne,SKIP,256);
  89. memset(m_pTableTwo,SKIP,256);  memset(m_pTableThree,SKIP,256);
  90. memset(m_pTableFour,SKIP,256); memset(m_pAllowable,false,256);
  91. *(m_pTableZero + '"') = DQSTART; *(m_pTableZero + ''')  = SQSTART;
  92. *(m_pTableZero + '/') = CMSTART; *(m_pTableOne + '"')    = DQEND;
  93. *(m_pTableTwo + ''') = SQEND;   *(m_pTableThree + 'n') = SLEND;
  94. *(m_pTableFour + '*') = MLEND;
  95. *(m_pAllowable + 'n') = true; *(m_pAllowable + 'r') = true;
  96. *(m_pAllowable + 't') = true; *(m_pAllowable + '') = true;
  97. *(m_pAllowable + ' ')  = true; *(m_pAllowable + ';')  = true;
  98. *(m_pAllowable + '(')  = true; *(m_pAllowable + ')')  = true;
  99. *(m_pAllowable + '{')  = true; *(m_pAllowable + '}')  = true;
  100. *(m_pAllowable + '[')  = true; *(m_pAllowable + ']')  = true;
  101. *(m_pAllowable + '*')  = true;
  102. }
  103. void CSyntaxColorizer::deleteTables()
  104. {
  105. delete m_pTableZero;  delete m_pTableOne;  delete m_pTableTwo;
  106. delete m_pTableThree; delete m_pTableFour; delete m_pAllowable;
  107. }
  108. void CSyntaxColorizer::AddKeyword(LPCTSTR Keyword, COLORREF cr, int grp)
  109. {
  110. LPTSTR token;
  111. //make a copy of Keyword so that strtok will operate correctly
  112. LPTSTR keyword = new TCHAR[strlen(Keyword) + 1];
  113. strcpy(keyword,Keyword);
  114. CHARFORMAT cf = m_cfDefault;
  115. cf.crTextColor = cr;
  116. token = strtok(keyword,",");
  117. while(token != NULL)
  118. {
  119. if(_stricmp(token,"rem") == 0)
  120. *(m_pTableTwo + 'n') = SLEND; //set single quote as comment start
  121. addKey(token,cf,grp);
  122. token = strtok(NULL,",");
  123. }
  124. delete keyword;
  125. }
  126. void CSyntaxColorizer::AddKeyword(LPCTSTR Keyword, CHARFORMAT cf, int grp)
  127. {
  128. LPTSTR token;
  129. //make a copy of Keyword so that strtok will operate correctly
  130. LPTSTR keyword = new TCHAR[strlen(Keyword) + 1];
  131. strcpy(keyword,Keyword);
  132. token = strtok(keyword,",");
  133. while(token != NULL)
  134. {
  135. if(_stricmp(token,"rem") == 0)
  136. *(m_pTableTwo + 'n') = SLEND; //set single quote as comment start
  137. addKey(token,cf,grp);
  138. token = strtok(NULL,",");
  139. }
  140. delete keyword;
  141. }
  142. void CSyntaxColorizer::addKey(LPCTSTR Keyword, CHARFORMAT cf, int grp) //add in ascending order
  143. {
  144. SKeyword* pskNewKey = new SKeyword;
  145. SKeyword* prev,*curr;
  146. //the string pointed to by Keyword is only temporary, so make a copy 
  147. // of it for our list
  148. pskNewKey->keyword = new TCHAR[strlen(Keyword)+1];
  149. strcpy(pskNewKey->keyword,Keyword);
  150. pskNewKey->keylen = strlen(Keyword);
  151. pskNewKey->cf = cf;
  152. pskNewKey->group = grp;
  153. pskNewKey->pNext = NULL;
  154. *(m_pTableZero + pskNewKey->keyword[0]) = KEYWORD;
  155. //if list is empty, add first node
  156. if(m_pskKeyword == NULL)
  157. m_pskKeyword = pskNewKey; 
  158. else
  159. {
  160. //check to see if new node goes before first node
  161. if(strcmp(Keyword,m_pskKeyword->keyword) < 0)
  162. {
  163. pskNewKey->pNext = m_pskKeyword;
  164. m_pskKeyword = pskNewKey;
  165. }
  166. //check to see if new keyword already exists at the first node
  167. else if(strcmp(Keyword,m_pskKeyword->keyword) == 0)
  168. {
  169. //the keyword exists, so replace the existing with the new
  170. pskNewKey->pNext = m_pskKeyword->pNext;
  171. delete m_pskKeyword->keyword; delete m_pskKeyword;
  172. m_pskKeyword = pskNewKey;
  173. }
  174. else
  175. {
  176. prev = m_pskKeyword;
  177. curr = m_pskKeyword->pNext;
  178. while(curr != NULL && strcmp(curr->keyword,Keyword) < 0)
  179. {
  180. prev = curr;
  181. curr = curr->pNext;
  182. }
  183. if(curr != NULL && strcmp(curr->keyword,Keyword) == 0)
  184. {
  185. //the keyword exists, so replace the existing with the new
  186. prev->pNext = pskNewKey;
  187. pskNewKey->pNext = curr->pNext;
  188. delete curr->keyword; delete curr;
  189. }
  190. else
  191. {
  192. pskNewKey->pNext = curr;
  193. prev->pNext = pskNewKey;
  194. }
  195. }
  196. }
  197. }
  198. void CSyntaxColorizer::ClearKeywordList()
  199. {
  200. SKeyword* pTemp = m_pskKeyword;
  201. while(m_pskKeyword != NULL)
  202. {
  203. *(m_pTableZero + m_pskKeyword->keyword[0]) = SKIP;
  204. if(_stricmp(m_pskKeyword->keyword,"rem") == 0)
  205. *(m_pTableTwo + 'n') = SKIP;
  206. pTemp = m_pskKeyword->pNext;
  207. delete m_pskKeyword->keyword;
  208. delete m_pskKeyword;
  209. m_pskKeyword = pTemp;
  210. }
  211. }
  212. CString CSyntaxColorizer::GetKeywordList()
  213. {
  214. CString sList;
  215. SKeyword* pTemp = m_pskKeyword;
  216. while(pTemp != NULL)
  217. {
  218. sList += pTemp->keyword;
  219. sList += ",";
  220. pTemp = pTemp->pNext;
  221. }
  222. sList.TrimRight(',');
  223. return sList;
  224. }
  225. CString CSyntaxColorizer::GetKeywordList(int grp)
  226. {
  227. CString sList;
  228. SKeyword* pTemp = m_pskKeyword;
  229. while(pTemp != NULL)
  230. {
  231. if(pTemp->group == grp)
  232. {
  233. sList += pTemp->keyword;
  234. sList += ",";
  235. }
  236. pTemp = pTemp->pNext;
  237. }
  238. sList.TrimRight(',');
  239. return sList;
  240. }
  241. void CSyntaxColorizer::SetCommentColor(COLORREF cr)
  242. {
  243. CHARFORMAT cf = m_cfComment;
  244. cf.dwMask = CFM_COLOR;
  245. cf.crTextColor = cr;
  246. SetCommentStyle(cf);
  247. }
  248. void CSyntaxColorizer::SetStringColor(COLORREF cr)
  249. {
  250. CHARFORMAT cf = m_cfString;
  251. cf.dwMask = CFM_COLOR;
  252. cf.crTextColor = cr;
  253. SetStringStyle(cf);
  254. }
  255. void CSyntaxColorizer::SetGroupStyle(int grp, CHARFORMAT cf)
  256. {
  257. SKeyword* pTemp = m_pskKeyword;
  258. while(pTemp != NULL)
  259. {
  260. if(pTemp->group == grp)
  261. {
  262. pTemp->cf = cf;
  263. }
  264. pTemp = pTemp->pNext;
  265. }
  266. }
  267. void CSyntaxColorizer::GetGroupStyle(int grp, CHARFORMAT &cf)
  268. {
  269. SKeyword* pTemp = m_pskKeyword;
  270. while(pTemp != NULL)
  271. {
  272. if(pTemp->group == grp)
  273. {
  274. cf = pTemp->cf;
  275. pTemp = NULL;
  276. }
  277. else
  278. {
  279. pTemp = pTemp->pNext;
  280. //if grp is not found, return default style
  281. if(pTemp == NULL) cf = m_cfDefault;
  282. }
  283. }
  284. }
  285. void CSyntaxColorizer::SetGroupColor(int grp, COLORREF cr)
  286. {
  287. CHARFORMAT cf;
  288. GetGroupStyle(grp,cf);
  289. cf.dwMask = CFM_COLOR;
  290. cf.crTextColor = cr;
  291. SetGroupStyle(grp,cf);
  292. }
  293. void CSyntaxColorizer::Colorize(CHARRANGE cr, CRichEditCtrl *pCtrl)
  294. {
  295. //Code optimization (old code deleted) by HOMO_PROGRAMMATIS <homo_programmatis@rt.mipt.ru>
  296. /**/ Colorize(cr.cpMin, cr.cpMax, pCtrl);
  297. //end of changes by HOMO_PROGRAMMATIS
  298. }
  299. void CSyntaxColorizer::Colorize(long nStartChar, long nEndChar, CRichEditCtrl *pCtrl)
  300. {
  301. //No Selection-splashing upgrade by HOMO_PROGRAMMATIS <homo_programmatis@rt.mipt.ru>
  302. /**/ CHARRANGE l_OldSelectionRange;
  303. /**/ pCtrl->GetSel(l_OldSelectionRange);
  304. /**/ SendMessage(pCtrl->m_hWnd, EM_HIDESELECTION, 1, 0);
  305. //end of changes by HOMO_PROGRAMMATIS
  306. long nTextLength = 0;
  307. if(nStartChar == 0 && nEndChar == -1) //send entire text of rich edit box
  308. {
  309. nTextLength = pCtrl->GetTextLength();
  310. //if there is alot of text in the Rich Edit (>64K) then GetWindowText doesn't
  311. //work. We have to select all of the text, and then use GetSelText
  312. pCtrl->SetSel(0,-1);
  313. }
  314. else
  315. {
  316. //set up the text buffer; add 1 because zero-based array
  317. nTextLength = nEndChar - nStartChar + 1;
  318. pCtrl->SetSel(nStartChar,nEndChar);
  319. }
  320. LPTSTR lpszBuf = new TCHAR[nTextLength+1];
  321. pCtrl->GetSelText(lpszBuf);
  322. pCtrl->SetSelectionCharFormat(m_cfDefault);
  323. colorize(lpszBuf,pCtrl,nStartChar);
  324. delete lpszBuf;
  325. //No Selection-splashing upgrade by HOMO_PROGRAMMATIS <homo_programmatis@rt.mipt.ru>
  326. /**/ pCtrl->SetSel(l_OldSelectionRange);
  327. /**/ SendMessage(pCtrl->m_hWnd, EM_HIDESELECTION, 0, 0);
  328. //end of changes by HOMO_PROGRAMMATIS
  329. }
  330. void CSyntaxColorizer::colorize(LPTSTR lpszBuf, CRichEditCtrl *pCtrl, long iOffset /*=0*/)
  331. {
  332. //setup some vars
  333. CHARFORMAT cf;
  334. LPTSTR lpszTemp;
  335. long iStart;
  336. long x = 0;
  337. SKeyword* pskTemp = m_pskKeyword;
  338. unsigned char* pTable = m_pTableZero;
  339. //do the work
  340. while(lpszBuf[x])
  341. {
  342. //Bug fix: some 'char's are actually negative - caused 'read-below-array' before fix
  343. //fixed by HOMO_PROGRAMMATIS <homo_programmatis@rt.mipt.ru>
  344. //old code
  345. // switch(pTable[lpszBuf[x]])
  346. //corrected variant
  347. /**/ switch(pTable[(_TUCHAR) lpszBuf[x]])
  348. //end of changes by HOMO_PROGRAMMATIS
  349. {
  350. case DQSTART:
  351. pTable = m_pTableOne;
  352. iStart = iOffset + x;
  353. break;
  354. case SQSTART:
  355. pTable = m_pTableTwo;
  356. iStart = iOffset + x;
  357. break;
  358. case CMSTART:
  359. if(lpszBuf[x+1] == '/')
  360. {
  361. pTable = m_pTableThree;
  362. iStart = iOffset + x;
  363. x++;
  364. }
  365. else if(lpszBuf[x+1] == '*')
  366. {
  367. pTable = m_pTableFour;
  368. iStart = iOffset + x;
  369. x++;
  370. }
  371. else if(lpszBuf[x] == ''')
  372. {
  373. pTable = m_pTableThree;
  374. iStart = iOffset + x;
  375. x++;
  376. }
  377. break;
  378. case MLEND:
  379. if(lpszBuf[x+1] == '/')
  380. {
  381. x++;
  382. pTable = m_pTableZero;
  383. pCtrl->SetSel(iStart,iOffset + x+1);
  384. pCtrl->SetSelectionCharFormat(m_cfComment);
  385. }
  386. break;
  387. case SLEND:
  388. if(lpszBuf[x-2] != '\') // line continuation character
  389. {
  390. pTable = m_pTableZero;
  391. pCtrl->SetSel(iStart,iOffset + x+1);
  392. pCtrl->SetSelectionCharFormat(m_cfComment);
  393. }
  394. break;
  395. case DQEND:
  396. pTable = m_pTableZero;
  397. pCtrl->SetSel(iStart,iOffset + x+1);
  398. pCtrl->SetSelectionCharFormat(m_cfString);
  399. break;
  400. case SQEND:
  401. if(lpszBuf[x-1] == '\' && lpszBuf[x+1] == ''')
  402. break;
  403. pTable = m_pTableZero;
  404. pCtrl->SetSel(iStart,iOffset + x+1);
  405. pCtrl->SetSelectionCharFormat(m_cfString);
  406. break;
  407. case KEYWORD:
  408. lpszTemp = lpszBuf+x;
  409. while(pskTemp != NULL)
  410. {
  411. if(pskTemp->keyword[0] == lpszTemp[0])
  412. {
  413. int x1=0,y1=0;iStart = iOffset + x;
  414. while(pskTemp->keyword[x1])
  415. {
  416. y1 += lpszTemp[x1] ^ pskTemp->keyword[x1];
  417. x1++;
  418. }
  419. if(y1 == 0 && (*(m_pAllowable + (lpszBuf[x-1])) && 
  420. *(m_pAllowable + (lpszBuf[x+pskTemp->keylen]))))
  421. {
  422. if(_stricmp(pskTemp->keyword,"rem") == 0)
  423. {
  424. pTable = m_pTableThree;
  425. }
  426. else 
  427. {
  428. x += pskTemp->keylen;
  429. pCtrl->SetSel(iStart,iOffset + x);
  430. pCtrl->SetSelectionCharFormat(pskTemp->cf);
  431. }
  432. }
  433. }
  434. pskTemp = pskTemp->pNext;
  435. }
  436. pskTemp = m_pskKeyword;
  437. break;
  438. case SKIP:;
  439. }
  440. x++;
  441. }
  442. //sometimes we get to the end of the file before the end of the string
  443. //or comment, so we deal with that situation here
  444. if(pTable == m_pTableOne)
  445. {
  446. cf = m_cfString;
  447. pCtrl->SetSel(iStart,iOffset + x+1);
  448. pCtrl->SetSelectionCharFormat(cf);
  449. }
  450. else if(pTable == m_pTableTwo)
  451. {
  452. cf = m_cfString;
  453. pCtrl->SetSel(iStart,iOffset + x+1);
  454. pCtrl->SetSelectionCharFormat(cf);
  455. }
  456. else if(pTable == m_pTableThree)
  457. {
  458. cf = m_cfComment;
  459. pCtrl->SetSel(iStart,iOffset + x+1);
  460. pCtrl->SetSelectionCharFormat(cf);
  461. }
  462. else if(pTable == m_pTableFour)
  463. {
  464. cf = m_cfComment;
  465. pCtrl->SetSel(iStart,iOffset + x+1);
  466. pCtrl->SetSelectionCharFormat(cf);
  467. }
  468. }