Scintilla library of jPBe

Share your advanced PureBasic knowledge/code with the community.
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Scintilla library of jPBe

Post by oryaaaaa »

Code updated For 5.20+

Code: Select all

    #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, "Scintilla example", #PB_Window_SystemMenu)

    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)
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

This looks like an excellent start ... could you provide the complete source for testcode.pb? Too many variables missing to run.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Here is a great scintilla example:

Code: Select all

#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, "Scintilla example", #PB_Window_SystemMenu)

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)
I like logic, hence I dislike humans but love computers.
Post Reply