Search code examples
c++cwinapisyntax-highlightingrichedit

Change character formatting of a range


I'm trying to realize a code to add the syntax-highlighting to the richedit of winapi, so I search ranges of text that I must colorize, but if I select the range with the EM_EXSETSEL message to format with the EM_SETCHARFORMAT message, it's very slow and all is saw by users. How I can change the character formatting more quickly ?


Solution

  • I did it via RTF: it's a markup language, conceptually similar to HTML. Insert the color directives at once and reload the buffer. To be true I used MFC, but I think that CRichEdit it's a thin layer that adds no further functionality (apart framework integration, of course). Here some code (very old, I'm sorry):

    ....
    
    // reformat line
    //
    void RichEditSyntaxColor::FmtLine(CRichEditCtrl &c, int nLine)
    {
        int iLine = c.LineIndex(nLine),
            lLine = c.LineLength(iLine);
        if (lLine > 0)
        {
            fmt(c, nLine, lLine);
    
            long ss, es;
            c.GetSel(ss, es);
            c.ShowWindow(SW_HIDE);
            stream(c, iLine, lLine);
            c.ShowWindow(SW_SHOW);
            c.SetSel(ss, es);
        }
    }
    
    // apply formatted streaming to selected pos
    //
    void RichEditSyntaxColor::stream(CRichEditCtrl &c, int iLine, int lLine)
    {
        c.SetSel(iLine, iLine + lLine);
        EDITSTREAM eds = { DWORD(this), 0, fmtLineCb };
        c.StreamIn(SF_RTF|SFF_SELECTION, eds);
    }       
    
    // required callback
    //
    DWORD CALLBACK RichEditSyntaxColor::fmtLineCb(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
    {
        RichEditSyntaxColor* pCookie = (RichEditSyntaxColor*)dwCookie;
        memcpy(pbBuff, pCookie->obuf, *pcb = pCookie->os.pcount());
        return 0;
    }
    
    // colors data, useful to configure
    //
    SyntaxColor::aColor SyntaxColor::_colorsDef[] = {
        {"Atom",    RGB( 16, 16, 32)},
        {"Number",  RGB(128, 32,128)},
        {"Var", RGB( 16, 16,255)},
        {"String",  RGB(128,128,128)},
        {"Comment", RGB(128,128, 20)}, //RGB( 32,128, 32)},
        {"SepChar", RGB(196, 32, 32)}
    };
    char SyntaxColor::_colorsStr[];
    
    void SyntaxColor::Table2String()
    {
        ostringstream s(_colorsStr);//, sizeof _colorsStr);
    
        s << "{\\colortbl;";
        for (int i = 0; i < __maxTag__; i++)
        {
            COLORREF c = _colorsDef[i].value;
            s << "\\red"    << int(GetRValue(c))
              << "\\green"  << int(GetGValue(c))
              << "\\blue"   << int(GetBValue(c))
              << ';';
        }
        s << '}' << ends;
    }
    ...