Reference: PureBasic Custom Lexer

Category: Controls - Scintilla

Date: 02-16-2022

Return to Index


 
'This is shown for reference only. It was pulled directly from
'the PureBasic Forum at http://www.purebasic.fr/english/viewtopic.php?t=19418
 
#SCI_GETCHARAT = 2007
#SCI_GETCURRENTPOS = 2008
#SCI_GETANCHOR = 2009
#SCI_GOTOLINE = 2024
#SCI_GOTOPOS = 2025
#SCI_SETANCHOR = 2026
#SCI_GETENDSTYLED = 2028
#SCI_STARTSTYLING = 2032
#SCI_SETSTYLING = 2033
#SCI_MARKERDEFINE = 2040
#SCI_MARKERSETFORE = 2041
#SCI_MARKERSETBACK = 2042
#SCI_STYLESETSIZE = 2055
#SCI_STYLESETFONT = 2056
#SCI_STYLECLEARALL = 2050
#SCI_STYLESETFORE = 2051
#SCI_STYLESETBOLD = 2053
#SCI_STYLESETITALIC = 2054
#SCI_GETLENGTH = 2006
#SCI_SETSEL = 2160
#SCI_LINEFROMPOSITION = 2166
#SCI_POSITIONFROMLINE = 2167
#SCI_SETTEXT = 2181
#SCI_GETTEXT = 2182
#SCI_GETDIRECTPOINTER = 2185
#SCI_SETCARETLINEVISIBLE = 2096
#SCI_SETCARETLINEBACK = 2098
#SCI_SETFOLDLEVEL = 2222
#SCI_GETFOLDLEVEL = 2223
#SCI_SETMARGINTYPEN = 2240
#SCI_APPENDTEXT = 2282
#SCI_TOGGLEFOLD = 2231
#SCI_SETMARGINWIDTHN = 2242
#SCI_SETMARGINMASKN = 2244
#SCI_SETMARGINSENSITIVEN = 2246
#SCI_SEARCHANCHOR = 2366
#SCI_SEARCHNEXT = 2367
#SCI_SETLEXER = 4001
 
#SC_MARGIN_NUMBER = 1
#SC_FOLDLEVELBASE = $400
#SC_FOLDLEVELHEADERFLAG = $2000
#SC_MASK_FOLDERS = $FE000000
 
#STYLE_DEFAULT = 32
 
#SCLEX_CONTAINER = 0
#SCLEX_PUREBASIC = 67
 
#SC_MARK_CIRCLE = 0
#SC_MARK_ROUNDRECT = 1
#SC_MARK_ARROW = 2
#SC_MARK_SMALLRECT = 3
#SC_MARK_SHORTARROW = 4
#SC_MARK_EMPTY = 5
#SC_MARK_ARROWDOWN = 6
#SC_MARK_MINUS = 7
#SC_MARK_PLUS = 8
#SC_MARK_VLINE = 9
#SC_MARK_LCORNER = 10
#SC_MARK_TCORNER = 11
#SC_MARK_BOXPLUS = 12
#SC_MARK_BOXPLUSCONNECTED = 13
#SC_MARK_BOXMINUS = 14
#SC_MARK_BOXMINUSCONNECTED = 15
#SC_MARK_LCORNERCURVE = 16
#SC_MARK_TCORNERCURVE = 17
#SC_MARK_CIRCLEPLUS = 18
#SC_MARK_CIRCLEPLUSCONNECTED = 19
#SC_MARK_CIRCLEMINUS = 20
#SC_MARK_CIRCLEMINUSCONNECTED = 21
#SC_MARK_BACKGROUND = 22
#SC_MARK_DOTDOTDOT = 23
#SC_MARK_ARROWS = 24
#SC_MARK_PIXMAP = 25
#SC_MARK_FULLRECT = 26
#SC_MARK_CHARACTER = 10000
 
#SC_MARKNUM_FOLDEREND = 25
#SC_MARKNUM_FOLDEROPENMID = 26
#SC_MARKNUM_FOLDERMIDTAIL = 27
#SC_MARKNUM_FOLDERTAIL = 28
#SC_MARKNUM_FOLDERSUB = 29
#SC_MARKNUM_FOLDER = 30
#SC_MARKNUM_FOLDEROPEN = 31
 
#SCN_STYLENEEDED = 2000
#SCN_CHARADDED = 2001
#SCN_SAVEPOINTREACHED = 2002
#SCN_SAVEPOINTLEFT = 2003
#SCN_MODIFYATTEMPTRO = 2004
#SCN_KEY = 2005
#SCN_DOUBLECLICK = 2006
#SCN_UPDATEUI = 2007
#SCN_MODIFIED = 2008
#SCN_MACRORECORD = 2009
#SCN_MARGINCLICK = 2010
#SCN_NEEDSHOWN = 2011
#SCN_PAINTED = 2013
#SCN_USERLISTSELECTION = 2014
#SCN_URIDROPPED = 2015
#SCN_DWELLSTART = 2016
#SCN_DWELLEND = 2017
#SCN_ZOOM = 2018
#SCN_HOTSPOTCLICK = 2019
#SCN_HOTSPOTDOUBLECLICK = 2020
#SCN_CALLTIPCLICK = 2021
#SCN_AUTOCSELECTION = 2022
 
#INDICS_MASK = $E0
 
Structure NotifyHeader
    *hwndFrom.l
    idFrom.l
    Code.l
EndStructure
 
Structure SCNotification
    Nmhdr.NotifyHeader
    position.l
    ch.l
    modifiers.l
    modificationType.l
    *Text.l
    length.l
    linesAdded.l
    message.l
    wParam.l
    lParam.l
    Line.l
    foldLevelNow.l
    foldLevelPrev.l
    Margin.l
    listType.l
    x.l
    y.l
EndStructure
 
Enumeration 0
    #LexerState_Space
    #LexerState_Comment
    #LexerState_Keyword
    #LexerState_FoldKeyword
EndEnumeration
 
Prototype.l ScintillaDirect(sciptr.l, Msg.l, param1.l = 0, param2.l = 0)
Global Scintilla.ScintillaDirect, sciptr.l
Global scihWnd.l, oldproc.l
 
Procedure LoadFile()
    filename.s = OpenFileRequester("Open a file...", "", "PureBasic (*.pb)|*.pb|All files (*.*)|*.*", 0)
    If filename <> ""
        file.l = ReadFile(#PB_Any, filename)
        If file <> 0
            Len.l = Lof(file)
            *mem = AllocateMemory(Len)
            If *mem
                ReadData(file, *mem, Len)
                Scintilla(sciptr, #SCI_SETTEXT, 0, *mem)
                FreeMemory(*mem)
            EndIf
            CloseFile(file)
        EndIf
    EndIf
EndProcedure
 
Procedure SaveFile()
    filename.s = SaveFileRequester("Save a file...", "", "PureBasic (*.pb)|*.pb|All files (*.*)|*.*", 0)
    If filename <> ""
        file.l = CreateFile(#PB_Any, filename)
        If file <> 0
            Len.l = Scintilla(sciptr, #SCI_GETLENGTH) + 1
            *mem = AllocateMemory(Len)
            If *mem
                Scintilla(sciptr, #SCI_GETTEXT, Len, *mem)
                WriteData(file, *mem, Len)
                FreeMemory(*mem)
            EndIf
            CloseFile(file)
        EndIf
    EndIf
EndProcedure
 
Procedure FindText()
    Text.s = InputRequester("Scintilla test", "Enter text to search for", "")
    If Text <> ""
        current.l = Scintilla(sciptr, #SCI_GETCURRENTPOS)
        Scintilla(sciptr, #SCI_SETANCHOR, current)
        Scintilla(sciptr, #SCI_SEARCHANCHOR)
        start.l = Scintilla(sciptr, #SCI_SEARCHNEXT, 0, @Text)
        If Pos <> -1
            anchor.l = Scintilla(sciptr, #SCI_GETANCHOR)
            Scintilla(sciptr, #SCI_SETSEL, start, anchor)
        EndIf
    EndIf
    SetFocus_(scihWnd)
EndProcedure
 
Procedure GotoLine()
    Line.s = InputRequester("Scintilla test", "Enter line to go to", "1")
    lineno.l = Val(Line)
    If lineno > 0
        Scintilla(sciptr, #SCI_GOTOLINE, lineno - 1)
    EndIf
    SetFocus_(scihWnd)
EndProcedure
 
Procedure ToggleCurrentFold()
    Pos.l = Scintilla(sciptr, #SCI_GETCURRENTPOS)
    Line.l = Scintilla(sciptr, #SCI_LINEFROMPOSITION, Pos)
    Scintilla(sciptr, #SCI_TOGGLEFOLD, Line)
EndProcedure
 
Procedure Highlight(sciptr.l, startpos.l, endpos.l)
    Debug(sciptr)
    If startpos = -1
        endstyled.l = Scintilla(sciptr, #SCI_GETENDSTYLED)
        linenumber.l = Scintilla(sciptr, #SCI_LINEFROMPOSITION, endstyled)
    Else
        linenumber = Scintilla(sciptr, #SCI_LINEFROMPOSITION, startpos)
    EndIf
 
    If linenumber = 0
        level = #SC_FOLDLEVELBASE
    Else
        linenumber - 1
        level = Scintilla(sciptr, #SCI_GETFOLDLEVEL, linenumber) & ~ #SC_FOLDLEVELHEADERFLAG
    EndIf
 
    thislevel.l = level
    nextlevel.l = level
 
    currentpos.l = Scintilla(sciptr, #SCI_POSITIONFROMLINE, linenumber)
    Scintilla(sciptr, #SCI_STARTSTYLING, currentpos, $1f | #INDICS_MASK)
    State = #LexerState_Space
    startkeyword = currentpos
    keyword.s = ""
 
    While currentpos <= endpos
        oldstate = State
        char.l = Scintilla(sciptr, #SCI_GETCHARAT, currentpos)
        If char = ';'
            State = #LexerState_Comment
        ElseIf char = 10 Or char = 13
            State = #LexerState_Space
        ElseIf State <> #LexerState_Comment
            If char = 9 Or char = ' ' Or char = '.'
                State = #LexerState_Space
            Else
                State = #LexerState_Keyword
                keyword + Chr(char)
            EndIf
        EndIf
        If oldstate <> State Or currentpos = endpos
            If oldstate = #LexerState_Keyword
                lkeyword.s = LCase(keyword)
                If lkeyword = "procedure"
                    thislevel | #SC_FOLDLEVELHEADERFLAG
                    nextlevel + 1
                    oldstate = #LexerState_FoldKeyword
                ElseIf lkeyword = "endprocedure"
                    nextlevel - 1
                    If nextlevel < #SC_FOLDLEVELBASE
                        nextlevel = #SC_FOLDLEVELBASE
                    EndIf
                    oldstate = #LexerState_FoldKeyword
                EndIf
                keyword = ""
            EndIf
            Scintilla(sciptr, #SCI_SETSTYLING, currentpos - startkeyword, oldstate)
            startkeyword = currentpos
        EndIf
 
        If char = 10 Or currentpos = endpos
            Scintilla(sciptr, #SCI_SETFOLDLEVEL, linenumber, thislevel)
            thislevel = nextlevel
            linenumber + 1
        EndIf
 
        currentpos + 1
    Wend
EndProcedure
 
Procedure ScintillaWindowCallback(hWnd.l, Msg.l, wParam.l, lParam.l)
    result.l = 0
    Select Msg
        Case #WM_NOTIFY
            *lpnmhdr.Nmhdr = lParam
            *Notify.SCNotification = lParam
            Select *lpnmhdr\Code
                Case #SCN_STYLENEEDED
                    Highlight(sciptr, -1, *Notify\position)
                Case #SCN_MARGINCLICK
                    modifiers = *Notify\modifiers
                    position = *Notify\position
                    Margin = *Notify\Margin
                    linenumber = Scintilla(sciptr, #SCI_LINEFROMPOSITION, position)
                    Select Margin
                        Case 2
                            Scintilla(sciptr, #SCI_TOGGLEFOLD, linenumber)
                    EndSelect
            EndSelect
        Default
            result = CallWindowProc_(oldproc, hWnd, Msg, wParam, lParam)
    EndSelect
    ProcedureReturn result
EndProcedure
 
file.s = "scilexer.dll"
 
scihmod = OpenLibrary(#PB_Any, "SciLexer.dll")
If scihmod = 0
    MessageRequester("Error", "Cannot open SciLexer.dll")
    End
EndIf
 
OpenWindow(0, 0, 0, 600, 400, #PB_Window_SystemMenu, "Scintilla example")
 
CreateMenu(0, WindowID(0))
MenuTitle("File")
MenuItem(1, "Open...")
MenuItem(2, "Save As...")
MenuItem(3, "Quit")
MenuTitle("Edit")
MenuItem(4, "Find...")
MenuItem(5, "Goto...")
MenuItem(6, "Toggle current fold")
 
GetClientRect_(WindowID(0), rect.RECT)
scihWnd = CreateWindowEx_(#WS_EX_CLIENTEDGE, "Scintilla", "", #WS_CHILD | #WS_VISIBLE | #WS_TABSTOP, 0, 0, rect\right, rect\bottom, WindowID(0), 0, GetModuleHandle_(0), 0)
 
Scintilla = GetFunction(scihmod, "Scintilla_DirectFunction")
sciptr = SendMessage_(scihWnd, #SCI_GETDIRECTPOINTER, 0, 0)
 
oldproc.l = SetWindowLong_(WindowID(0), #GWL_WNDPROC, @ScintillaWindowCallback())
 
Choose a lexer
Scintilla(sciptr, #SCI_SETLEXER, #SCLEX_CONTAINER, 0)
 
Set Default Font
Scintilla(sciptr, #SCI_STYLESETFONT, #STYLE_DEFAULT, @"Courier New")
Scintilla(sciptr, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 16)
Scintilla(sciptr, #SCI_STYLECLEARALL)
 
Set caret Line colour
Scintilla(sciptr, #SCI_SETCARETLINEBACK, $eeeeff)
Scintilla(sciptr, #SCI_SETCARETLINEVISIBLE, #True)
 
Set styles For custom lexer
Scintilla(sciptr, #SCI_STYLESETFORE, #LexerState_Comment, $bb00)
Scintilla(sciptr, #SCI_STYLESETITALIC, #LexerState_Comment, 1)
Scintilla(sciptr, #SCI_STYLESETFORE, #LexerState_Keyword, 0)
Scintilla(sciptr, #SCI_STYLESETFORE, #LexerState_FoldKeyword, $ff)
 
; Margins
Scintilla(sciptr, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER)
Scintilla(sciptr, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS)
Scintilla(sciptr, #SCI_SETMARGINWIDTHN, 0, 50)
Scintilla(sciptr, #SCI_SETMARGINWIDTHN, 2, 20)
Scintilla(sciptr, #SCI_SETMARGINSENSITIVEN, 2, #True)
 
Choose folding icons
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_CIRCLEMINUS)
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDER, #SC_MARK_CIRCLEPLUS)
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERSUB, #SC_MARK_VLINE)
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERTAIL, #SC_MARK_LCORNERCURVE)
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEREND, #SC_MARK_CIRCLEPLUSCONNECTED)
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPENMID, #SC_MARK_CIRCLEMINUSCONNECTED)
Scintilla(sciptr, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERMIDTAIL, #SC_MARK_TCORNERCURVE)
 
Choose folding Icon colours
Scintilla(sciptr, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDER, $FFFFFF)
Scintilla(sciptr, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDER, 0)
Scintilla(sciptr, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF)
Scintilla(sciptr, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, 0)
Scintilla(sciptr, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPENMID, 0)
Scintilla(sciptr, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERSUB, 0)
Scintilla(sciptr, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERTAIL, 0)
Scintilla(sciptr, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERMIDTAIL, 0)
 
Set some sample Text
Text.s = "; A custom Scintilla lexer example" + #CRLF$
Text + "Procedure hello()" + #CRLF$
Text + "  Debug(" + Chr(34) + "Woo" + Chr(34) + ")" + #CRLF$
Text + "EndProcedure"
Scintilla(sciptr, #SCI_SETTEXT, 0, @Text)
 
RemoveKeyboardShortcut(0, #PB_Shortcut_Tab)
RemoveKeyboardShortcut(0, #PB_Shortcut_Tab | #PB_Shortcut_Shift)
 
quit.l = #False
Repeat
    Event.l = WaitWindowEvent()
    Select Event
        Case #PB_Event_CloseWindow
            quit = #True
        Case #PB_Event_Menu
            Select EventMenu()
                Case 1 : LoadFile()
                Case 2 : SaveFile()
                Case 3 : quit = #True
                Case 4 : FindText()
                Case 5 : GotoLine()
                Case 6 : ToggleCurrentFold()
            EndSelect
    EndSelect
Until quit
 
DestroyWindow_(scihWnd)
CloseLibrary(scihmod)
 
'gbs_00675
'Date: 03-10-2012


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm