Seite 1 von 4

SyntaxHighlighting für PB4.10 (ScintillaGadget)

Verfasst: 08.06.2007 00:05
von ts-soft
Da die Frage immer wieder aufkommt, hab ich mal den folgenden Code
aus einem anderen Projekt extrahiert und angepaßt.
Erstellt wird ein Fenster mit 2 ScinttillaGagets in einem Splitter. (SplitView)
SyntaxHighlightning durch Nutzung der DLL aus dem PB-SDK.

Farben werden aus den Preferences der PB-IDE gelesen.

Code: Alles auswählen

EnableExplicit

Define.s HighLightDLLPath = #PB_Compiler_Home + "Library SDK\Syntax Highlighting\SyntaxHilighting.dll"

If OpenLibrary(0, HighLightDLLPath) = #False : Debug "HL-DLL nicht gefunden" : End : EndIf
If InitScintilla("scintilla.dll") = #False : Debug "Scintilla-DLL nicht gefunden" : End : EndIf

Prototype SyntaxHighlight(*Buffer, len.l, callback.l, asm.l)
Global SyntaxHighlight.SyntaxHighlight = GetFunction(0, "SyntaxHighlight")

Enumeration; Gadgets
  #SciID
  #SciID2
  #Splitter
EndEnumeration

Enumeration; Syntax
  #SYNTAX_Text
  #SYNTAX_Keyword
  #SYNTAX_Comment
  #SYNTAX_Constant
  #SYNTAX_String
  #SYNTAX_Function
  #SYNTAX_Asm
  #SYNTAX_Operator
  #SYNTAX_Structure
  #SYNTAX_Number
  #SYNTAX_Pointer
  #SYNTAX_Separator
  #SYNTAX_Label
EndEnumeration

Define.l start_pos, Buffer, Editor

Procedure.s GetSpecialFolder(CSIDL.l)
  Protected *itemid.ITEMIDLIST
  Protected location.s = Space(#MAX_PATH)

  If SHGetSpecialFolderLocation_ (0, CSIDL, @*itemid) = #NOERROR
    If SHGetPathFromIDList_(*itemid, @location)
      If Right(location, 1) <> "\" : location + "\" : EndIf
      ProcedureReturn location
    EndIf
  EndIf
EndProcedure

Procedure SHCallback(pos, len, id)
  Shared start_pos,Buffer, Editor

  ScintillaSendMessage(Editor, #SCI_STARTSTYLING, (pos - Buffer) + start_pos, $1F)
  ScintillaSendMessage(Editor, #SCI_SETSTYLING, len, id)
EndProcedure

Procedure ScintillaCallBack(EditorGadget.l, *scinotify.SCNotification)
  Protected line_number.l
  Protected txtr.TEXTRANGE
  Protected end_pos.l
  Shared start_pos, Buffer, Editor
  
  Editor = EditorGadget
  If *scinotify\nmhdr\code = #SCN_STYLENEEDED
    line_number = ScintillaSendMessage(EditorGadget, #SCI_LINEFROMPOSITION, ScintillaSendMessage(EditorGadget, #SCI_GETENDSTYLED))
    start_pos = ScintillaSendMessage(EditorGadget, #SCI_POSITIONFROMLINE, line_number)
    end_pos     = *scinotify\Position

    txtr\chrg\cpMin = start_pos
    txtr\chrg\cpMax = end_pos
    txtr\lpstrText  = AllocateMemory(end_pos - start_pos + 1)
    Buffer          = txtr\lpstrText

    ScintillaSendMessage(EditorGadget, #SCI_GETTEXTRANGE, 0, txtr)
    SyntaxHighlight(Buffer, end_pos - start_pos, @SHCallback(), #False)

    FreeMemory(Buffer)
  EndIf
EndProcedure

Procedure CreatePBSourceView()
  Protected WFlags.l = #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_Invisible | #PB_Window_SystemMenu | #PB_Window_SizeGadget
  Protected temp.s
  If OpenWindow(1, #PB_Ignore, 0, 640, 480, "Scintilla Beispiel", WFlags)
    SmartWindowRefresh(1, #True)
    CreateGadgetList(WindowID(1))
    ScintillaGadget(#SciID, 0, 0, 0, 0, @ScintillaCallBack())
    ScintillaGadget(#SciID2, 0, 0, 0, 0, 0)
    ScintillaSendMessage(#SciID2, #SCI_SETDOCPOINTER, 0, ScintillaSendMessage(#SciID, #SCI_GETDOCPOINTER))
    SplitterGadget(#Splitter, 0, 0, 0, 0, #SciID, #SciID2)
    SetGadgetState(#Splitter, 0)

    ScintillaSendMessage(#SciID, #SCI_SETLEXER, #SCLEX_CONTAINER)
    ScintillaSendMessage(#SciID2, #SCI_SETLEXER, #SCLEX_CONTAINER)

    OpenPreferences(GetSpecialFolder(#CSIDL_APPDATA) + "PureBasic\PureBasic.prefs")
    PreferenceGroup("Editor")
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE,#STYLE_DEFAULT, $000000)
    ScintillaSendMessage(#SciID, #SCI_STYLESETBACK, #STYLE_DEFAULT, ReadPreferenceLong("BackgroundColor", $FFFFFF))
    temp = ReadPreferenceString("EditorFontName", "Courier New")
    ScintillaSendMessage(#SciID, #SCI_STYLESETFONT, #STYLE_DEFAULT, @temp)
    ScintillaSendMessage(#SciID, #SCI_STYLESETSIZE, #STYLE_DEFAULT, ReadPreferenceLong("EditorFontSize", 10))
    ScintillaSendMessage(#SciID, #SCI_STYLECLEARALL)

    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Text, ReadPreferenceLong("NormalTextColor", 0))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Keyword, ReadPreferenceLong("BasicKeywordColor", $9D030D))
    ScintillaSendMessage(#SciID, #SCI_STYLESETBOLD, #SYNTAX_Keyword, #True)
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Comment, ReadPreferenceLong("CommentColor", $6F884A))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Constant, ReadPreferenceLong("ConstantColor", $0B46AE))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_String, ReadPreferenceLong("StringColor", $413C33))
    ScintillaSendMessage(#SciID, #SCI_STYLESETITALIC, #SYNTAX_String, #True)
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Function, ReadPreferenceLong("PureKeywordColor", $EF303D))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Asm, ReadPreferenceLong("ASMKeywordColor", $400080))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Operator,  ReadPreferenceLong("OperatorColor", $0000FF))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Structure, ReadPreferenceLong("StructureColor", $0548B4))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Number, ReadPreferenceLong("NumberColor", $0000FF))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Pointer,  ReadPreferenceLong("PointerColor", $0507B4))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Separator,  ReadPreferenceLong("SeparatorColor", $000000))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #SYNTAX_Label,  ReadPreferenceLong("LabelColor", $804000))
    ScintillaSendMessage(#SciID, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER)
    ScintillaSendMessage(#SciID, #SCI_SETMARGINWIDTHN, 0, 40)
    ScintillaSendMessage(#SciID, #SCI_STYLESETBACK, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberBackColor", GetSysColor_(15)))
    ScintillaSendMessage(#SciID, #SCI_STYLESETFORE, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberColor", 0))
    ScintillaSendMessage(#SciID, #SCI_SETMARGINWIDTHN, 1, 5)

    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #STYLE_DEFAULT, $000000)
    ScintillaSendMessage(#SciID2, #SCI_STYLESETBACK, #STYLE_DEFAULT, ReadPreferenceLong("BackgroundColor", $FFFFFF))
    temp = ReadPreferenceString("EditorFontName", "Courier New")
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFONT, #STYLE_DEFAULT, @temp)
    ScintillaSendMessage(#SciID2, #SCI_STYLESETSIZE, #STYLE_DEFAULT, ReadPreferenceLong("EditorFontSize", 10))
    ScintillaSendMessage(#SciID2, #SCI_STYLECLEARALL)

    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Text, ReadPreferenceLong("NormalTextColor", 0))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Keyword, ReadPreferenceLong("BasicKeywordColor", $9D030D))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETBOLD, #SYNTAX_Keyword, #True)
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Comment, ReadPreferenceLong("CommentColor", $6F884A))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Constant, ReadPreferenceLong("ConstantColor", $0B46AE))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_String, ReadPreferenceLong("StringColor", $413C33))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETITALIC, #SYNTAX_String, #True)
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Function, ReadPreferenceLong("PureKeywordColor", $EF303D))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Asm, ReadPreferenceLong("ASMKeywordColor", $400080))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Operator,  ReadPreferenceLong("OperatorColor", $0000FF))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Structure, ReadPreferenceLong("StructureColor", $0548B4))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Number, ReadPreferenceLong("NumberColor", $0000FF))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Pointer,  ReadPreferenceLong("PointerColor", $0507B4))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Separator,  ReadPreferenceLong("SeparatorColor", $000000))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #SYNTAX_Label,  ReadPreferenceLong("LabelColor", $804000))
    ScintillaSendMessage(#SciID2, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER)
    ScintillaSendMessage(#SciID2, #SCI_SETMARGINWIDTHN, 0, 40)
    ScintillaSendMessage(#SciID2, #SCI_STYLESETBACK, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberBackColor", GetSysColor_(15)))
    ScintillaSendMessage(#SciID2, #SCI_STYLESETFORE, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberColor", 0))
    ScintillaSendMessage(#SciID2, #SCI_SETMARGINWIDTHN, 1, 5)
    ClosePreferences()

    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure

If CreatePBSourceView()
  HideWindow(1, #False)
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow : Break
      Case #PB_Event_SizeWindow
        ResizeGadget(#Splitter, #PB_Ignore, #PB_Ignore, WindowWidth(1), WindowHeight(1))
    EndSelect
  ForEver  
EndIf 
Am besten einen Source reinpasten, da keine Load- oder Save-Routinen
implementiert sind

// Nachtrag:
angepaßt an PB4.10 Beta 2

Verfasst: 13.06.2007 20:19
von ts-soft
Hilfe zu Scintilla in chm Form erhaltet ihr hier:
http://www.purebasic.fr/german/viewtopi ... 089#156089
Danke an Kai :allright:

Verfasst: 14.06.2007 18:42
von Vermilion

Code: Alles auswählen

InitScintilla("scintilla.dll")
Geht nicht, ist keine Funktion, sagt der Compiler... :(

(Was hab ich denn jetzt schon wieder falsch gemacht? -.-°

Verfasst: 14.06.2007 18:50
von ts-soft
Vermilion hat geschrieben:

Code: Alles auswählen

InitScintilla("scintilla.dll")
Geht nicht, ist keine Funktion, sagt der Compiler... :(

(Was hab ich denn jetzt schon wieder falsch gemacht? -.-°
Lies den Titel!

Verfasst: 19.06.2007 08:30
von ts-soft
Ich hab mithilfe des obigen Codebeispiels mal ein kleines IDE-Addon
gebastelt. Einfach als Werkzeug eintragen, ohne jegliche Parameter. Bei
Aufruf liest es den Text des aktuell geöffneten Tabs (direkt aus dem Control,
Speicherung oder Tempfile nicht erforderlich) und stellt ihn schreibgeschützt
dar.
Dient also nur als Hilfe wenn man mehrere Tabs nebeneinander vergleichen
möchte (breiten Bildschirm vorausgesetzt :wink: )

Download: http://ts-soft.eu/dl/sourceviewer.zip

Vielleicht habt ihr ja noch eine Anregung was man da noch reinbasteln könnte :wink:

Funktioniert nur mit der PB-IDE ab Version 3.94

Verfasst: 19.06.2007 13:08
von Rings
irgendwie verstehe ich nicht (trotz 2maligen durchsehen des quellcodes)
wie denn nun definiert ist was zum bsp ein keyword,Kommentar oder Basicword währe respektive wie man das selber festlegt.

Ziel ist es einen Highlighter zu haben der zum Bsp auch eigene
Kommandos entsprechend färbt.

any idea ?

Verfasst: 19.06.2007 13:35
von ts-soft
Es wird immer ein Lexer benötigt. Dieser befindet sich entweder fertig in der
SciLexer.dll oder wie hier in einer Extra DLL. (selbstdefiniert hat Nr. 0)

Selbstdefinition ist auch möglich, siehe jaPBe, aber sehr aufwendig.
Das einfachste ist es einen fertigen Lexer wie z.B. #SCLEX_VB für Visual
Basic zu nehmen. Jetzt brauchste noch mehrere Wortlisten, z.B. Funktionen,
alle getrennt durch ein Leerzeichen, die kannste dann übergeben (Memorypointer).

Kommentarzeichen, Stringliterale usw. sind durch den Lexer definiert.
Den Wortgruppen noch die Farbe, Schriftstyle usw. zuordnen und fertig ist
das ganze.

Der Lexer weiß meist auch, was zu falten ist, man muß ihm nur sagen ob
gefaltet werden soll, oder eben nicht.

Fertigen Lexer aus SciLexer.dll nutzen ist recht einfach, selber einen
Lexer schreiben dann nicht mehr :wink:

Wenn es keine fertigen gibt, kann man auch einen ähnlichen verwenden,
solange die Kommentare gleich eingeleitet werden, Strings gleich
gekennzeichnet sind usw.

Ansonsten versuchen die Hilfe zu Scintilla zu verstehen :mrgreen:

Ich hoffe ich habe Dich wenigstens ein kleines bißchen erleuchtet

Gruß
Thomas

Verfasst: 19.06.2007 16:16
von Rings
ok, erstmal danke für deine Mühe hier.
Als ich nutze vbscript, dafür gibts nen eintrag in der lexer.
Eigentlich wäre das so okay, bis auf ein paar (150) eigene
Keywords (Funktionen) die ich auch gerne einfärben würde.
Jetzt brauchste noch mehrere Wortlisten, z.B. Funktionen,
alle getrennt durch ein Leerzeichen, die kannste dann übergeben (Memorypointer).
hättest du evtl. nen Hinweis , denn:

Die Doku ist ja übrigens unter aller Sau (also die von scintilla)
da find ich überhaubt nix.
Wüsste schon mal gerne wie man damit überhaupt arbeiten kann.
(Meinen Hut zieh an alle diedas geschafft haben)


Im Sourcecode gibts dann auch etliche von Konstanten.
Aber auch hier , schlecht dokumentiert.

Das heisst als resüme, ich weis mal wieder nicht wo man
anfangen soll.

Verfasst: 19.06.2007 18:11
von ts-soft
>> hättest du evtl. nen Hinweis , denn:
Zieh dir den Source und sieh in die header-dateien :mrgreen:
Lexer setzen siehste im obigen beispiel, genauso wie den font usw.
lediglich die konstanten müssen entsprechend dem lexer (header-dateien)
angepasst werden.
Keywörter:

Code: Alles auswählen

spice_keyword.s =  "blubber blabber sappelei"
ScintillaSendMessage(#Gadget, #SCI_SETKEYWORDS, #SCE_SPICE_KEYWORD, @spice_keyword)
Wobei ich die Sprache SPICE nicht kenne. Die konstanten für die
Wortgruppen liegen meist zwischen 1 - 8

Wenn Du die richtigen Konstanten für VBScript gefunden hast, im
Lexersource o. ä. :mrgreen: ist es eigentlich nicht mehr schwer

Die Doku von Scintilla ist mehr als mies
PS: Keywörter immer kleinschreiben für den Lexer!

// Edit:
Wenn Du die Doku für die Konstante nicht findest, setze eine Konstante
z.B. auf 1, ordne Keywörter, Schrift, Farbe usw. zu. Diese Konstante
solange erhöhen bis z.B. die Funktionen sich färben. Bei dem kleinen
Zahlenbereich (0 - 15 mehr kommt wohl nicht vor) kommste so auch zum Ziel :wink:

Verfasst: 19.06.2007 18:35
von Vermilion
Bezüglich meinem Post: :oops: hab noch 4.00, ich dachte das geht auch so...