Click here to Skip to main content
11,412,516 members (69,108 online)
Click here to Skip to main content

Syntax colorizing with Speller engine using TOM and CSAPI

, 12 Nov 2004
Rate this:
Please Sign up or sign in to vote.
Syntax colorizing with Speller engine using TOM and CSAPI.

Screen shot

Introduction

The demo enhances a CRichEditCtrl that provides basic syntax highlighting for C/C++ or any other languages. The CRichEditCtrl also provides an interface that checks spelling using the CSAPI and gives a screen feedback by a coloring underline. This demo uses intensively the TOM interface. The check of spelling occurs only in the comments part of a source code or in strings. The control provides highlighting keywords not only in the source code but also for Doxygen in the comments.

Implementation

For a better implementation, the project has been organized into three classes. CSyntaxcolor manages comments, strings and keyword detection. CSpellingChecker manages the spelling of keywords and manages dictionaries. CSyntaxColorSpellChecker inherits from CSyntaxcolor and overloads the highlighting to provide a coloring underline feedback for the CRichEditCtrl.

Strategy

In order to avoid problems with the redraw of the control, I used Text Object Model (TOM) interface. This interface allows to manipulate runs of characters without sad effects on the screen, and gives more functions than the Win32 API. You can, for example, disable the undo during the modifications of colors. For the spelling, I used CSAPI. There is only some documentation about this API, but it eases considerably the implementation of a spell engine. It allows you to use many standardized dictionaries in your application. I am not sure if it is an official API from Microsoft.

Points of Interest

The main problem to handle syntax highlighting correctly is to manage the multi-line comments without re-computing each time colors of the complete file. The change of only one character could affect the entire file. Re-computing the complete file takes time and slows down the process of typing. To detect the modification of the multi-line comment structure, there is no clean solution. My solution has been to overload the notification EN_MSGFILTER of the CRichEditCtrl. When the user types a character able to change the state of the multi-line comments, I set a flag. And I do a fast analysis of the current line in order to know if the comment is opened or closed.

void CDemoEditorView::OnMsgfilterEdit(NMHDR* pNMHDR, LRESULT* pResult) 
{
  MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
  if(pMsgFilter->msg == WM_CHAR)
  {
    switch(pMsgFilter->wParam)
    {
      case '*':
      case '/':
        {
          m_bChangeAll = true;
          break;// '*' comment could affect all the file
        }
    }
    CHARRANGE cr;
    GetRichEditCtrl().GetSel(cr);
    if(cr.cpMax -cr.cpMin)// when we remove, it could remove '*/' or '/*'
    {
      m_bChangeAll = true;
    }
  }
  if(pMsgFilter->msg == WM_KEYDOWN)
  {
    switch(pMsgFilter->wParam)
    {
      case VK_BACK:
      case VK_DELETE:
      case VK_RETURN:
        m_bChangeAll = true;
        break;
    }
  }
  if(m_bChangeAll)
  {
    CHARRANGE cr;
    GetRichEditCtrl().GetSel(cr);
    m_nextedComments  = 
     m_colorizer.AnalyseMultiCommentLine(GetRichEditCtrl().LineFromChar(cr.cpMin));
  }
  *pResult = 0;
}

Using Colorizer

I consider the colorization of a text as a set of styles in a run of characters. A style includes all properties for a string (color, font, size, …). The ITextRange interface handles the concept of style through the functions GetSyle and SetStyle. Most of the time, this property is not used in a default implementation, but this LONG is stored in the run. I have stored in this value, the index of the highlight class. It is now very easy to quickly continue a multi line comment style when I evaluate only a part of the file. The style is stored directly in the run of characters. The main job of coloring is done in the function ColorizeRange(…). You can customize the keywords with the function AddKeyList(…). It will be easy to customize this class for HTML, XML, or other languages. You can customize the comments and string detection by changing CreateCommentsAndStringsTags(…). Also, you can change and add more highlight styles by changing CreateDefaultStyle().

void CSyntaxColor::CreateDefaultStyle()
{
    m_tStyle.SetSize(styleMax);
    // black for normal
    m_tStyle[normal]    = CKeyStyle(RGB(0,0,0));
    // blue for syntax
    m_tStyle[syntax]    = CKeyStyle(RGB(0,0,255));
    // Gray for directives
    m_tStyle[directive] = CKeyStyle(RGB(192,192,192));
    // blue for pragma
    m_tStyle[pragma]    = CKeyStyle(RGB(0,0,255));
    // green  multi comment green
    m_tStyle[mcomments] = CKeyStyle(RGB(0,200,0));
    // green  single comment green
    m_tStyle[scomments] = CKeyStyle(RGB(0,200,0));
    // blue string
    m_tStyle[sstring]   = CKeyStyle(RGB(0,0,255));
    // blue string
    m_tStyle[dstring]   = CKeyStyle(RGB(0,0,255));
    // red keyword comments and bold
    m_tStyle[highlightComments]= CKeyStyle(RGB(255,0,0),bold);
}

For each word in the NormalSlot or the CommentSlot, ColorizeRange calls OnColorKeyWord(int istart ,int iend ,LPCSTR pword, HighLightStyle style) to colorize a keyword.

Using the Speller

To implement the spelling checker in syntax colorizing, I have created a new class derived from CSyntaxcolor. The class includes an object CSpellingChecker and overload OnColorKeyWord(…). The new class continues the job of OnColorKeyWord done in CSyntaxcolor, and checks where the colorization occurs, checks the spelling, and sets the underline to signal a misspelled word.

bool CSyntaxColorSpellChecker::OnColorKeyWord(int istart, int iend, 
                          LPCSTR pword, HightLightStyle style)
{
    if(CSyntaxColor::OnColorKeyWord(istart,iend,pword,style)) return true;
    long newunderline = 0;
    if(style == scomments || style == mcomments || 
                             style == sstring || style == dstring )
    {
        newunderline = m_cSpeller.CheckWord(pword) ? 0: SPELL_UNDERLINE;
    }
    m_pRange->SetRange(istart,iend);
    ITextFont *pFont;
    m_pRange->GetFont(&pFont);
    pFont->SetUnderline(newunderline);
    pFont->Release();
    return false;
}

You can change the language of the speller by passing another LID to the function Initialize(lidFrench, lidDutch,…). Just make sure before that the dictionary and the spell engine is rightly installed in the registry. CSpellingChecker also provides some tools to manage dictionaries and words suggestion through a set of functions. Suggestion word comes not only from the main dictionary (.LEX) but also from your user dictionary.

bool CheckWord(LPCSTR pWord);
bool SuggestWords(LPCSTR pWord,int max, CStringArray & tList );
bool IgnoreAlways(LPCSTR pWord);
bool AddToUserDic(LPCSTR pWord);

It is possible to add more user dictionaries (read only) in the function InitEngine, if you modify the SIB structure for each call of SuggestWords and CheckWord. These extra dictionaries can be constructed automatically from your source code, in order to check the spelling of function names, variables, etc…

The Demo

The demo just implements the three classes in a text editor. I have added syntax highlighting and spell checking in comments to a basic application created by Visual C++. The editor is configured for C++ keywords highlight and Doxygen keywords in the comments.

History

  • 11/11/2004 - first version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

William Hennebois
Web Developer
France France
No Biography provided

Comments and Discussions

 
SuggestionMy method start programm without spelling Pin
Member 2146768 at 14-Nov-13 22:37
memberMember 214676814-Nov-13 22:37 
GeneralDidnt get it running Pin
auge__ at 22-Mar-10 6:17
memberauge__22-Mar-10 6:17 
GeneralThis Colorizer works very well Pin
rob_toutant at 24-Nov-09 22:32
memberrob_toutant24-Nov-09 22:32 
GeneraltomWave at Win98 problem Pin
vblazheyev@gmail.com at 29-Sep-05 6:36
membervblazheyev@gmail.com29-Sep-05 6:36 
GeneralCan't find TOM.h Pin
solikang at 14-Jun-05 16:50
membersolikang14-Jun-05 16:50 
GeneralRe: Can't find TOM.h Pin
William Hennebois at 14-Jun-05 21:16
memberWilliam Hennebois14-Jun-05 21:16 
GeneralRe: Can't find TOM.h Pin
solikang at 15-Jun-05 1:55
membersolikang15-Jun-05 1:55 
GeneralRe: Can't find TOM.h Pin
William Hennebois at 22-Jun-05 10:10
memberWilliam Hennebois22-Jun-05 10:10 
GeneralRe: Can't find TOM.h Pin
William Hennebois at 22-Jun-05 10:11
memberWilliam Hennebois22-Jun-05 10:11 
QuestionTOM interface is great but is incomplete? Pin
Alexandru at 27-Jan-05 3:12
memberAlexandru27-Jan-05 3:12 
QuestionHtml support? Pin
are_all_nicks_taken_or_what at 6-Dec-04 16:20
memberare_all_nicks_taken_or_what6-Dec-04 16:20 
GeneralUnhandled exception in DemoEditor.exe Pin
MayaRafi at 17-Nov-04 21:14
memberMayaRafi17-Nov-04 21:14 
GeneralRe: Unhandled exception in DemoEditor.exe Pin
Anonymous at 21-Nov-04 21:56
sussAnonymous21-Nov-04 21:56 
GeneralRe: Unhandled exception in DemoEditor.exe Pin
ak99372 at 27-Feb-05 23:51
memberak9937227-Feb-05 23:51 
GeneralA small problem: You're not allowed to use Microsoft's dictionaries! Pin
Mike Eriksson at 15-Nov-04 23:08
memberMike Eriksson15-Nov-04 23:08 
GeneralRe: A small problem: You're not allowed to use Microsoft's dictionaries! Pin
danmorin at 16-Nov-04 4:53
memberdanmorin16-Nov-04 4:53 
GeneralRe: A small problem: You're not allowed to use Microsoft's dictionaries! Pin
Gerhold at 16-Nov-04 6:33
memberGerhold16-Nov-04 6:33 
GeneralRe: A small problem: You're not allowed to use Microsoft's dictionaries! Pin
danmorin at 9-Jun-05 5:17
memberdanmorin9-Jun-05 5:17 
GeneralC# Code Pin
skjagini at 13-Nov-04 14:58
memberskjagini13-Nov-04 14:58 
GeneralSample binary crashes Pin
YoSilver at 13-Nov-04 11:48
memberYoSilver13-Nov-04 11:48 
GeneralRe: Sample binary crashes Pin
William Hennebois at 13-Nov-04 23:21
memberWilliam Hennebois13-Nov-04 23:21 
GeneralRe: Sample binary crashes Pin
YoSilver at 14-Nov-04 14:01
memberYoSilver14-Nov-04 14:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150427.1 | Last Updated 12 Nov 2004
Article Copyright 2004 by William Hennebois
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid