Syntax Highlighting

Icyculyr

Active member
Joined
Feb 26, 2008
Messages
25
Programming Experience
1-3
Hi, I am wondering what the best way to highlight syntax is, without lag..

I am quite interested in how the Visual Basic syntax is done so fast.

Is using regex the fastest way to go? after about 15-20 words on the screen that match, it goes incredibly fast..

ColorLines() takes sometimes 1-2 seconds with 15-20, and probably 5-6 seconds with 30+

This is currently what I am doing: (project attached below)

VB.NET:
Imports System.Text.RegularExpressions.Regex
Imports System.Text.RegularExpressions
Public Class Form1
#Region " [API's] "
    Public Declare Function LockWindowUpdate Lib "user32" (ByVal hWnd As Integer) As Integer
#End Region
#Region " [Variables] "
    Public wlList As New WordList()
#End Region
#Region " [Classes] "
#Region " [WordList] "
    Public Class WordList
        Private _cColor As New List(Of Color)
        Private _sWord As New List(Of String)
        Public Function Add(ByVal sWord As String, ByVal cColor As Color) As Object
            _sWord.Add(sWord)
            _cColor.Add(cColor)
            Return Nothing
        End Function
        Public Function GetColor(ByVal iIndex As Integer) As Color
            Return _cColor(iIndex)
        End Function
        Public Function GetWord(ByVal iIndex As Integer) As String
            Return _sWord(iIndex)
        End Function
        Public Function Length() As Integer
            Return _sWord.Count
        End Function
    End Class
#End Region
#End Region
#Region " [Functions] "
#Region " [LastVisibleLine] "
    Public Function LastVisibleLine() As Integer
        Return rtbEdit.GetLineFromCharIndex(rtbEdit.GetCharIndexFromPosition(New Point(0, rtbEdit.Height)))
    End Function
#End Region
#Region " [FirstVisibleLine] "
    Public Function FirstVisibleLine() As Integer
        Return rtbEdit.GetLineFromCharIndex(rtbEdit.GetCharIndexFromPosition(New Point(0, -rtbEdit.Font.Height)))
    End Function
#End Region
#End Region
#Region " [Enums] "
#Region " [EditMessages] "
    Public Enum EditMessages
        LineIndex = 187
        LineFromChar = 201
        GetFirstVisibleLine = 206
        CharFromPos = 215
        PosFromChar = 1062
    End Enum
#End Region
#End Region
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim cColor As Color = Color.Blue
        wlList.Add("\bint\b", cColor)
        wlList.Add("\bbool\b", cColor)
        wlList.Add("\bstring\b", cColor)
        wlList.Add("\bfloat\b", cColor)
        wlList.Add("\bif\b", cColor)
        cColor = Color.Red
        wlList.Add(";", cColor)
    End Sub
    Public Function ColorLines() As Object
        LockWindowUpdate(rtbEdit.Handle.ToInt32())
        Dim iLineFirst As Integer = FirstVisibleLine()
        Dim iLineLast As Integer = LastVisibleLine()
        Dim sText As String = ""
        Dim iSelectionStart As Integer = rtbEdit.SelectionStart
        If rtbEdit.Lines.Length < 1 Then
            LockWindowUpdate(0)
            rtbEdit.SelectionLength = 0
            rtbEdit.SelectionStart = iSelectionStart
            rtbEdit.SelectionColor = Color.Black
            Application.DoEvents()
            Return Nothing
        End If
        Dim iLastIndexFound As Integer = 0
        For i As Integer = iLineFirst To iLineLast
            sText = rtbEdit.Lines(i)
            rtbEdit.SelectionStart = rtbEdit.GetFirstCharIndexFromLine(i)
            rtbEdit.SelectionLength = rtbEdit.Lines(i).Length
            rtbEdit.SelectionColor = Color.Black
            rtbEdit.SelectionLength = 0
            Dim sTextCopy1 As String = sText
            Dim iFirstCharOfLine As Integer = rtbEdit.GetFirstCharIndexFromLine(i)
            Dim iCharStart As Integer = 0
            For k As Integer = 0 To wlList.Length - 1
                Dim r As New Regex(wlList.GetWord(k), RegexOptions.Compiled)
                Dim mc As MatchCollection = r.Matches(sText)
                For Each mMatch As Match In mc
                    rtbEdit.SelectionStart = iFirstCharOfLine + mMatch.Index
                    rtbEdit.SelectionLength = mMatch.Length
                    rtbEdit.SelectionColor = wlList.GetColor(k)
                    Label1.Text = sText & ControlChars.NewLine & " iFirstCharOfLine: " & iFirstCharOfLine & ControlChars.NewLine & " Length: " & mMatch.Length
                Next mMatch
            Next k
            rtbEdit.SelectionLength = 0
            rtbEdit.SelectionStart = iSelectionStart
            rtbEdit.SelectionColor = Color.Black
        Next i
        LockWindowUpdate(0)
        Application.DoEvents()
        Return Nothing
    End Function
    Private Sub rtbEdit_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rtbEdit.TextChanged
        ColorLines()
    End Sub

    Private Sub rtbEdit_VScroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rtbEdit.VScroll
        'need to detect when the scroll finished.
    End Sub
End Class

Does anyone know a faster or better way?

Thanks
 

Attachments

  • RegexTest.zip
    63.3 KB · Views: 14
I think that part of the trick is only altering the highlighting on bits that have changed, doing it in a separate thread, and throttling it so it doesn't recalculate too often.
 
Back
Top