Version 1.40 - Quelques colorations supplémentaires.
#Style_JS_Number, #Style_JS_String , #Style_JS_Bracket, #Style_JS_Parentheses
ColorizeJSNumbers(gadget, startPos, endPos) - Coloration des nombres.
ColorizeJSStrings(gadget, startPos, endPos) - Coloration des string entre guillemets.
ColorizeJSBrackets(gadget, startPos, endPos) - Coloration des brackets '{' '}' '[' ']'
Ces colorations sont exécutées dans la procédure ColorizeHTMLTags().
.
Code : Tout sélectionner
; WebBase - Trame d'un editeur HTML/JavaScript
; Version 1.40
; PureBasic 6.30 (x64)
; Mise à jour du 2 Février 2026
; Pas d'API & Scintilla natif
; Fonctionnalités
; ===============
; Mise en place du gadget Scintilla
; Propriété du gadget Scintilla
; Scintilla callback pour gérer les évenements Scintilla
; Indentation
; Autocomplétion
; Coloration des mots clés HTML
; Coloration des commentaires
; Folding (Pliage et dépliage du code)
; Coloration des mots clés Javascript
; Auto-fermeture des tag <tag> -> </tag> automatique
; Coloration CSS
; Ajout
; Coloration des nombres
; Coloration des strings entre guillemets
; Coloration des brackets
; Coloration des parenthéses
EnableExplicit
Enumeration window
#app
EndEnumeration
Enumeration gadgets
#editor
EndEnumeration
Enumeration styles
#Style_HTML_Comment
#Style_HTML_Keyword
#Style_JS_Comment
#Style_JS_KeyWord
#Style_JS_Number
#Style_JS_String
#Style_JS_Bracket
#Style_JS_Parentheses
#Style_CSS_Selector
#Style_CSS_Property
#Style_CSS_Value
#Style_CSS_Number
#Style_CSS_String
#Style_CSS_Comment
#Style_CSS_Punct
EndEnumeration
Define version.s = "1.40"
; Liste des mots clés (C'est un jeu de test)
Global htmlKeyWords.s = "html,head,body,title,script,style,div,canvas,meta,h1,h2,h3,h4,h5,h6,button,p"
; Liste des mots clés Javascript (C'est un jeu de test)
Global jsKeywords.s = "break,case,catch,class,const,continue,debugger,default,delete,do," +
"else,export,extends,finally,for,function,if,import,in,instanceof," +
"let,new,return,super,switch,this,throw,try,typeof,var,void,while," +
"with,yield,await,enum,implements,interface,package,private," +
"protected,public,static,null,true,false,undefined"
; Liste des mots clés déclencheur de pliage/dépliage de code (C'est un jeu de test)
Global KeywordsFolding.s = "html,head,body,div,section,article,nav,ul,ol,table"
; Liste des mots clés CSS propriétés (C'est un jeu de test)
Global cssProperties.s = "color,background,background-color,margin,padding,width,height,display," +
"position,top,left,right,bottom,font-size,font-family,border,border-radius," +
"box-shadow,opacity,z-index|overflow,text-align,line-height"
; Liste des mots clé CSS valeur (C'est un jeu de test)
Global cssValues.s = "auto,inherit,initial,unset,none,block,inline,flex,grid,absolute,relative,fixed," +
"sticky,solid,dashed,center,cover,contain,Repeat,no-Repeat,bold,italic,hidden,visible," +
"lightblue,white,silver,gray,black,red,maroon,yellow,olive,lime,aqua,teal,blue,navy,fuchsia,purple"
; Séparateur des mots clés
Global KeyWordSep.s = ","
; Largeur de la marge de numérotation des lignes
Global scMarginSizeDefault = 50
; Couleurs
Global scFrontColor = RGB(105,105, 105)
Global scBackColor = RGB(250, 240, 230)
Global scCurrentLineColor = RGB(255, 228, 181)
Global scMasterFolder = RGB(255, 0, 0)
; Police de caractére
Global scFont.s = "Lucida Console"
Global scFontSize = 12
; Couleur des styles par defaut
Global scStyleHTMLKeyWordColor = RGB(255, 0, 0)
Global scStyleHTMLCommentColot = RGB(0, 255, 0)
Global scStyleJSCommentColor = RGB(0, 255, 0)
Global scStyleJSKeywordColor = RGB(0, 0, 205)
Global scStyleJSNumber = RGB(0, 180, 200)
Global scStyleJSString = RGB(160, 90, 200)
Global scStyleJSSBracket = RGB(0, 0, 255)
Global scStyleJSParentheses = RGB(255, 0, 0)
Global scStyleCSSKeywordColor = RGB(0, 0, 205)
Global scStyleCSSProperty = RGB(0, 120, 255)
Global scStyleCSSValue = RGB(0, 170, 120)
; Indentation
Global scIndent, scLine, scPos, scCol
; Pour la recherche des blocs commentaires "<!--" et "-->"
; Ces deux chaines doivent être stockées dans un buffer UTF8
Global commentStartPattern = AllocateMemory(5)
Global commentEndPattern = AllocateMemory(4)
Global commentCSSStartPattern = AllocateMemory(5)
Global commentCSSEndPattern = AllocateMemory(4)
;- Sommaire des procédures
; Définir les paramétres du gadget scintilla
Declare ScintillaProperties(gadget)
; Callback évenementielle du gadget scintilla
Declare ScintillaCallBack(gadget, *scn.scNotification)
; Obtenir le texte de la ligne en cours de saisie
Declare.s GetScintillaLineText(gadget, line)
; Obtenir le mot se trouvant entre deux position
Declare.s getScintillaWord(gadget, startPos, endPos)
; Tester si un mot est un mot clé
Declare.b isKeyword(word.s, keyWords.s)
; Déterminer le string précédent le curseur de saisie
Declare.s GetOpeningTagBeforeCaret(gadget)
; Tester si un mot est une clé de pliage
Declare.b isFoldingKeyWord(word.s, keyWordfoldingDown.s)
; Vérifier que la coloration du code JavaScript se trouve entre les balise <script> </script>
Declare.b IsInsideScriptBlock(gadget, pos)
; Coloration des mots clés HTML
Declare ColorizeHTMLTags(gadget, startPos, endPos, keyWords.s)
; Ignorer les lignes de commentaires JavaScript "//"
Declare SkipJSLineComment(gadget, pos)
; Ignorer les blocs de commentaires JavaScript "/* .. */"
Declare SkipJSBlockComment(gadget, pos)
; Coloration des mots clés JavaScript
Declare ColorizeJSKeywords(gadget, startPos, endPos)
; Coloration des mots clés JavaScript
Declare ColorizeJSComments(gadget, startPos, endPos)
; Coloration des nomnbres
Declare ColorizeJSNumbers(gadget, startPos, endPos)
; Coloration des string entre guillemets
Declare ColorizeJSStrings(gadget, startPos, endPos)
; Coloration des brackets '{' '}' '[' ']'
Declare ColorizeJSBrackets(gadget, startPos, endPos)
; Coloration des parenthéses
Declare ColorizeJSParentheses(gadget, startPos, endPos)
; Mettre à jour le pliage/dépliage
Declare UpdateHTMLFolding(gadget, KeywordsFolding.s)
; Retourne les positions de début et fin du code CSS
Declare GetCSSRange(gadget, *start.Integer, *end.Integer)
; Colorer des mots clés CSS
Declare ColorizeCSS(gadget, startPos, endPos)
; Texte au format UTF8
Declare MakeUTF8Text(text.s)
;- Fenetre de l'application
OpenWindow(#app, 0, 0, 800, 600, "WebBase " + version, #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
; Neutraliser la touche TAB et les caractéres spéciaux
RemoveKeyboardShortcut(#app, #PB_Shortcut_Tab)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_B, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_G, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_E, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_R, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_O, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_P, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_Q, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_S, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_F, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_H, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_K, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_W, 0)
AddKeyboardShortcut(#app, #PB_Shortcut_Control+#PB_Shortcut_N, 0)
; Editeur Scintilla gadget associé à un callback
ScintillaGadget(#editor, 10, 10, 780, 580, @scintillaCallBack())
;- Parametres Scintilla (Couleur, font, numerotation, style, etc ...)
ScintillaProperties(#editor)
; Positionner le curseur de saisie dans l'éditeur
SetActiveGadget(#editor)
; "<!--" et "-->" convertis au format UTF8
PokeS(commentStartPattern, "<!--", -1, #PB_UTF8)
PokeS(commentEndPattern, "-->", -1, #PB_UTF8)
PokeS(commentCSSStartPattern, "/*", -1, #PB_UTF8)
PokeS(commentCSSEndPattern, "*/", -1, #PB_UTF8)
;- Boucle évenementielle
Repeat : Until WaitWindowEvent(10) = #PB_Event_CloseWindow
;-
;- Liste des procédures
; Parametres du gadget scintilla
Procedure ScintillaProperties(gadget)
;- 1 Style par défaut
; Couleur et police de caractéres
ScintillaSendMessage(gadget, #SCI_STYLESETFORE, #STYLE_DEFAULT, scFrontColor)
ScintillaSendMessage(gadget, #SCI_STYLESETBACK, #STYLE_DEFAULT, scBackColor)
ScintillaSendMessage(gadget, #SCI_STYLESETFONT,#STYLE_DEFAULT, @scFont)
ScintillaSendMessage(gadget, #SCI_STYLESETSIZE, #STYLE_DEFAULT, scFontSize)
;- 2 Propager vers tous les styles
ScintillaSendMessage(gadget, #SCI_STYLECLEARALL)
;- 3 Définir des styles spécifiques
; Activation et couleur de la ligne en cours d'édition
ScintillaSendMessage(gadget, #SCI_SETCARETLINEVISIBLE, #True)
ScintillaSendMessage(gadget, #SCI_SETCARETLINEBACK, scCurrentLineColor)
; Les tabulations sont remplacées par des espaces
ScintillaSendMessage(gadget, #SCI_SETUSETABS, #False)
; Nombre d'espaces pour une tabulation
ScintillaSendMessage(gadget, #SCI_SETINDENT, 4)
; Création de la colonne de numérotation des lignes
ScintillaSendMessage(gadget, #SCI_SETMARGINTYPEN, 1, #SC_MARGIN_NUMBER)
ScintillaSendMessage(gadget, #SCI_SETMARGINWIDTHN, 1, scMarginSizeDefault)
; Autocomplétion : Parametres de la liste des mots clés
ScintillaSendMessage(gadget, #SCI_AUTOCSETMAXHEIGHT, 40)
ScintillaSendMessage(gadget, #SCI_AUTOCSETMAXWIDTH, 150)
ScintillaSendMessage(gadget, #SCI_AUTOCSETAUTOHIDE, #True)
ScintillaSendMessage(gadget, #SCI_AUTOCSETCHOOSESINGLE, #True)
ScintillaSendMessage(gadget, #SCI_AUTOCSETIGNORECASE, #True)
; Autocomplétion : Caractére séparant chaque mot de la liste des mots clés
ScintillaSendMessage(gadget, #SCI_AUTOCSETSEPARATOR, Asc(KeyWordSep))
; Autocomplétion : Caractére sélectionnant le mot de la liste d'autocomplétion
ScintillaSendMessage(gadget, #SCI_AUTOCSETFILLUPS, 0, @" ")
; Autocomplétion : Tri de la liste
ScintillaSendMessage(gadget, #SCI_AUTOCSETORDER, #SC_ORDER_PERFORMSORT)
; Folding : Création de la colonne de pliages/dépliage
ScintillaSendMessage(gadget, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS)
ScintillaSendMessage(gadget, #SCI_SETMARGINWIDTHN, 2, 20)
ScintillaSendMessage(gadget, #SCI_SETMARGINSENSITIVEN, 2, #True)
; Folding : Choix des icones de pliages du code 5
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_CIRCLEMINUS)
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDER, #SC_MARK_CIRCLEPLUS)
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERSUB, #SC_MARK_VLINE) ;Ligne verticale
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERTAIL, #SC_MARK_LCORNERCURVE) ;fin arborescence
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEREND, #SC_MARK_CIRCLEPLUSCONNECTED) ;Dépliage
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPENMID, #SC_MARK_CIRCLEMINUSCONNECTED) ;Pliage
ScintillaSendMessage(gadget, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERMIDTAIL, #SC_MARK_TCORNERCURVE)
; Folding : Couleur des icones de pliages/dépliage
ScintillaSendMessage(gadget, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDER, scMasterFolder)
ScintillaSendMessage(gadget, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDER, RGB(0, 0, 0))
ScintillaSendMessage(gadget, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, scMasterFolder)
ScintillaSendMessage(gadget, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, RGB(0, 0, 0))
ScintillaSendMessage(gadget, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPENMID, RGB(0, 0, 0))
ScintillaSendMessage(gadget, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERSUB, RGB(0, 0, 0))
ScintillaSendMessage(gadget, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERTAIL, RGB(0, 0, 0))
ScintillaSendMessage(gadget, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERMIDTAIL, RGB(0, 0, 0))
;- Folding : Activation du folding
ScintillaSendMessage(gadget, #SCI_SETMARGINTYPEN, 2, #SC_MARGIN_SYMBOL)
ScintillaSendMessage(gadget, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS)
ScintillaSendMessage(gadget, #SCI_SETMARGINSENSITIVEN, 2, 1)
ScintillaSendMessage(gadget, #SCI_SETMARGINWIDTHN, 2, 20)
;ScintillaSendMessage(gadget, #SCI_SETPROPERTY, @"fold", @"2")
;- Définit les styles
; Styles : Coloration des mots clés HTML
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_HTML_Keyword, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_HTML_Keyword, scStyleHTMLKeyWordColor)
; Style commentaires HTML
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_HTML_Comment, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_HTML_Comment, scStyleHTMLCommentColot)
; Styles : Coloration des commentaire JavaScript
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_Comment, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_Comment, scStyleJSCommentColor)
; Styles : Coloration des commentaire JavaScript
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_Comment, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_Comment, scStyleJSCommentColor)
; Styles : Coloration des mots clés JavaScript
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_KeyWord, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_KeyWord, scStyleJSKeywordColor)
; Styles : Coloration des Nombres JavaScript
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_Number, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_Number, scStyleJSNumber)
; Styles : Strings JS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_String, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_String, scStyleJSString)
; Styles : Brackets JS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_Bracket, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_Bracket, scStyleJSSBracket)
; Styles : Parentheses JS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_JS_Parentheses, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_JS_Parentheses, scStyleJSParentheses)
; Styles : Sélecteurs CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_Selector, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_Selector, scStyleCSSKeywordColor)
; Syles : Propriétés CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_Property, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_Property, scStyleCSSProperty)
; Styles : Valeurs CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_Value, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_Value, RGB(0, 170, 120))
; Styles : Nombres CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_Number, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_Number, RGB(0, 200, 200))
; Styles : Strings CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_String, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_String, RGB(180, 0, 180))
; Styles : Commentaires CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_Comment, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_Comment, RGB(0, 150, 0))
; Styles : Ponctuation CSS
ScintillaSendMessage(gadget, #SCI_INDICSETSTYLE, #Style_CSS_Punct, #INDIC_TEXTFORE)
ScintillaSendMessage(gadget, #SCI_INDICSETFORE, #Style_CSS_Punct, RGB(200, 200, 0))
EndProcedure
;-
; Callback evenementielle du gadget scintilla
Procedure scintillaCallBack(gadget, *scn.scNotification)
Protected textLength
Protected SciCurrentPos, SciWordStartPos
Protected curPos, curPos2
Protected *buf, *buf2
Protected tag.s ; Rechercher le tag entre "<" et ">" pour auto-fermeture du tag
Protected close.s ; Création du tag de fermeture "</tag>
Protected cssStart, cssEnd ; Ou commence et se termine la déclaration du code CSS
; Calculer la longueur du texte contenu dans le gadget scintilla
textLength = ScintillaSendMessage(gadget, #SCI_GETLENGTH)
; Analyser les evenement scintilla
Select *scn\nmhdr\code
Case #SCN_CHARADDED
; Un caractére est saisie
Select *scn\ch
Case 13
;- Indentation
; Vous avez pressé la touche entrée
; Quel est la position du décalages du texte au niveau de la marge.
scIndent = ScintillaSendMessage(gadget, #SCI_GETLINEINDENTATION, scLine)
; Passer à la ligne suivante
; et positionner le curseur
ScintillaSendMessage(gadget, #SCI_SETLINEINDENTATION, scLine+1, scIndent)
; Touche entrée préssée : Le curseur ne passera pas à la ligne suivante.
; Forcer le passage à la ligne en insérant la longueur de #CRLF$
If scIndent=0
scPos = scPos + Len(#CRLF$)
EndIf
; Positionner le curseur de saisie
ScintillaSendMessage(gadget, #SCI_GOTOPOS, scPos + scIndent)
Case 'a' To 'z', 'A' To 'Z'
;- Autocomplétion (Affichage d'une liste contenant les mots clés HTML
; Affichage du mot selectionné si autocomplétion
SciCurrentPos = ScintillaSendMessage(gadget, #SCI_GETCURRENTPOS)
SciWordStartPos = ScintillaSendMessage(gadget, #SCI_WORDSTARTPOSITION, SciCurrentPos, 1)
ScintillaSendMessage(0, #SCI_AUTOCSHOW, SciCurrentPos - SciWordStartPos, MakeUTF8Text(htmlKeyWords))
Case '>'
;- Auto fermeture de tag <tag>|</tag>
; Obtenir le tag de fermeture
tag = GetOpeningTagBeforeCaret(gadget)
If tag <> ""
curPos2 = ScintillaSendMessage(gadget, #SCI_GETCURRENTPOS, 0, 0)
close = "</" + tag + ">"
*buf2 = AllocateMemory(StringByteLength(close, #PB_UTF8) + 1)
PokeS(*buf2, close, -1, #PB_UTF8)
ScintillaSendMessage(gadget, #SCI_INSERTTEXT, curPos2, *buf2)
FreeMemory(*buf2)
; On ne modidie pas la position du curseur.
; Il est positionné entre le tag d'ouverture et le tag de fermeture
EndIf
EndSelect
Case #SCN_UPDATEUI
; Une mise à jour du gadget Scintilla est effectué
; Style & folding UNIQUEMENT si le contenu change
If *scn\updated & #SC_UPDATE_CONTENT
; Coloration HTML et Javascript
ColorizeHTMLTags(gadget, 0, textLength, htmlKeyWords)
; Coloration CSS
GetCSSRange(gadget, @cssStart, @cssEnd)
If cssStart <> -1 And cssEnd > cssStart
ColorizeCSS(gadget, cssStart, cssEnd)
EndIf
; Folding
UpdateHTMLFolding(gadget, KeywordsFolding)
EndIf
Case #SCN_MARGINCLICK
; Mise en oeuvre du pliage dépliage (folding)
; Clique sur la deuxiéme colonne
If *scn\margin = 2
; Ligne réelle à partir de la position du clic
Protected line = ScintillaSendMessage(gadget, #SCI_LINEFROMPOSITION, *scn\position, 0)
Protected level = ScintillaSendMessage(gadget, #SCI_GETFOLDLEVEL, line, 0)
; Autoriser uniquement sur les lignes HEADER
If level & #SC_FOLDLEVELHEADERFLAG
ScintillaSendMessage(gadget, #SCI_TOGGLEFOLD, line)
EndIf
EndIf
EndSelect
; Important pour le fonctionnement de l'indentation
; Trouver la position du curseur de saisie
scPos = ScintillaSendMessage(gadget, #SCI_GETANCHOR)
; Trouver la ligne ou se touve le curseur
scLine = ScintillaSendMessage(gadget, #SCI_LINEFROMPOSITION, scPos)
; Trouver la colonne en cours
scCol = ScintillaSendMessage(gadget, #SCI_GETCOLUMN, scPos)
EndProcedure
;-
; Obtenir le texte de la ligne en cours de saisie
Procedure.s getScintillaLineText(gadget, line)
Protected lineLength, *buffer, result.s
; Longueur de la ligne
lineLength = ScintillaSendMessage(gadget, #SCI_LINELENGTH, line)
; Initialisation du buffer UTF8
*buffer = AllocateMemory(lineLength + 1)
If *buffer > 0
; Obtenir et renvoyer le contenu de la ligne
ScintillaSendMessage(gadget, #SCI_GETLINE, line, *buffer)
result.s = PeekS(*buffer, -1, #PB_UTF8)
FreeMemory(*buffer)
EndIf
ProcedureReturn result
EndProcedure
; Obtenir le mot (ou texte) se trouvant entre deux positions
Procedure.s getScintillaWord(gadget, startPos, endPos)
Protected tr.scTextRange, *buffer, length, result.s
length = endPos - startPos
If length > 0
*buffer = AllocateMemory(length + 1)
tr\chrg\cpMin = startPos
tr\chrg\cpMax = endPos
tr\lpstrText = *buffer
ScintillaSendMessage(gadget, #SCI_GETTEXTRANGE, 0, @tr)
; Lecture UTF-8 correcte
result = PeekS(*buffer, -1, #PB_UTF8)
FreeMemory(*buffer)
EndIf
ProcedureReturn result
EndProcedure
; Tester si un mot est un mot clé
Procedure.b isKeyword(word.s, keyWords.s)
Protected countWords = CountString(keyWords, KeyWordSep), n
Protected result.b
For n = 1 To countWords + 1
If LCase(StringField(keyWords, n, KeyWordSep)) = LCase(word)
result = #True
EndIf
Next
ProcedureReturn result
EndProcedure
; Rechercher le tag précédent le curseur de saisie
Procedure.s GetOpeningTagBeforeCaret(gadget)
Protected curPos, startPos, endPos, text.s, name.s, i, ch
; Déterminer la position du curseur
curPos = ScintillaSendMessage(gadget, #SCI_GETCURRENTPOS, 0, 0)
startPos = curPos - 2 ; juste avant '>'
If startPos < 0 : ProcedureReturn "" : EndIf
; Remonter jusqu'à '<'
For i = startPos To 0 Step -1
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, i, 0)
If ch = '<'
startPos = i
Break
EndIf
Next
If ch <> '<' : ProcedureReturn "" : EndIf
; lire le contenu <...>
endPos = curPos - 1
text = GetScintillaWord(gadget, startPos, endPos)
text = Trim(text)
; Rejeter </tag> et <br/>
If Left(text, 2) = "</" : ProcedureReturn "" : EndIf
If Right(text, 2) = "/>" : ProcedureReturn "" : EndIf
; Extraire nom après '<'
For i = 2 To Len(text)
ch = Asc(Mid(text, i, 1))
If (ch >= 'a' And ch <= 'z') Or (ch >= 'A' And ch <= 'Z') Or
(ch >= '0' And ch <= '9') Or ch = '-' Or ch = '_'
name + Chr(ch)
Else
Break
EndIf
Next
ProcedureReturn name
EndProcedure
; Tester si un mot trouvé dans un string déclenche le folding
Procedure.b isFoldingKeyWord(text.s, keyWordsfolding.s)
Protected countWords, n
Protected result.b
; Compter le nombre de mots clés folding contenu dans la variable KeyWordsFolding
countWords = CountString(keyWordsfolding, KeyWordSep)
; Pour chaque mots clé folding
For n = 1 To countWords + 1
; Vérifier que le mot clé se trouve dans dans la chaine reçu
; Il doit se trouver au début (Position 1) de la chaine testé (text.s)
If FindString(LCase(text), LCase(StringField(keyWordsfolding, n, KeyWordSep))) = 1
result = #True
EndIf
Next
ProcedureReturn result
EndProcedure
Procedure.b IsInsideScriptBlock(gadget, pos)
Protected textStart = 0
Protected textEnd = pos
Protected text.s = GetScintillaWord(gadget, textStart, textEnd)
Protected openCount = CountString(LCase(text), "<script")
Protected closeCount = CountString(LCase(text), "</script>")
If openCount > closeCount
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;-
; Coloration des mots clés
Procedure ColorizeHTMLTags(gadget, startPos, endPos, keyWords.s)
Protected pos ; Position actuelle de l'indice de parcours du string
Protected lowerTag ; Position du prochain "<"
Protected upperTag ; Position du prochain ">"
Protected tagStart ; Premier caractère après "<"
Protected tagEnd ; Fin du nom de la balise sans ">"
Protected originalTagStart ; Début logique de la balise (après "<")
Protected tagName.s ; Tag sans balise d'ouverture/fermeture "<tag> -> "tag"
Protected nameStart ; Premier caractère après "<"
Protected isClosing ; Indicateur de balise fermée
Protected space ; Position d'un espace à l'intérieur de "<" et ">"
Protected commentStart, commentEnd ;Position de début et fin d'un commentaire
; La coloration se fera en plusieurs passage
; - 1 Commentaires
; - 2 Tags HTML <tag> </tag>
; Reset des indicateurs de styles
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_HTML_Comment, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORCLEARRANGE, startPos, endPos - startPos)
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_HTML_Keyword, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORCLEARRANGE, startPos, endPos - startPos)
;- ■ 1 Pass commentaires <!-- Commentaire -->
pos = startPos
While pos < endPos
; Définir le target de recherche
ScintillaSendMessage(gadget, #SCI_SETTARGETSTART, pos)
ScintillaSendMessage(gadget, #SCI_SETTARGETEND, endPos)
; Rechercher la chaine de début de commentaire "<!--" (Longueur 4)
commentStart = ScintillaSendMessage(gadget, #SCI_SEARCHINTARGET, 4, commentStartPattern)
; Il y en a pas, on s'arrete !
If commentStart = -1 : Break : EndIf
; Nouveau target de recherche qui commencera aprés "<!--"
ScintillaSendMessage(gadget, #SCI_SETTARGETSTART, commentStart + 4)
ScintillaSendMessage(gadget, #SCI_SETTARGETEND, endPos)
; Rechercher la chaine de fin de commentaire "-->" (Longueur 3)
commentEnd = ScintillaSendMessage(gadget, #SCI_SEARCHINTARGET, 3, commentEndPattern)
If commentEnd <> -1
commentEnd + 3
Else
commentEnd = endPos
EndIf
; colorer le commentaire
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_HTML_Comment)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, commentStart, commentEnd - commentStart)
pos = commentEnd
Wend
;- ■ 2 Pass tag HTML "<html>"
pos = startPos
While pos < endPos
; Définir le target de recherche
ScintillaSendMessage(gadget, #SCI_SETTARGETSTART, pos)
ScintillaSendMessage(gadget, #SCI_SETTARGETEND, endPos)
; Chercher le caractére '<' dans la zone de scan
lowerTag = ScintillaSendMessage(gadget, #SCI_SEARCHINTARGET, 1, @"<")
; Il y en a pas. On sort de la boucle
If lowerTag = -1 : Break : EndIf
; "<" est trouvé
; Nouveau target de recherche qui commencera aprés "<"
ScintillaSendMessage(gadget, #SCI_SETTARGETSTART, lowerTag + 1)
ScintillaSendMessage(gadget, #SCI_SETTARGETEND, endPos)
; Chercher le prochain '>'
upperTag = ScintillaSendMessage(gadget, #SCI_SEARCHINTARGET, 1, @">")
If upperTag = -1
;ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_HTML_Keyword, 0)
;ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, lowerTag, 1)
Break
EndIf
; Bonne nouvelle nous avons maintenant localisé "<" et ">"
originalTagStart = lowerTag + 1
tagStart = originalTagStart
; Nouveau target de recherche qui commencera aprés "<" et se termine à ">"
ScintillaSendMessage(gadget, #SCI_SETTARGETSTART, tagStart)
ScintillaSendMessage(gadget, #SCI_SETTARGETEND, upperTag)
; Recherche du caractéres espace dans las chaine située entre "<" et ">"
space = ScintillaSendMessage(gadget, #SCI_SEARCHINTARGET, 1, @" ")
If space = -1
tagEnd = upperTag
Else
tagEnd = space
EndIf
; Rechercher le mot situé entre "<" et ">"
If tagEnd > tagStart
tagName = GetScintillaWord(gadget, tagStart, tagEnd)
isClosing = #False
nameStart = tagStart
; Détecter </tag>
If Left(tagName, 1) = "/"
isClosing = #True
tagName = Mid(tagName, 2)
nameStart = tagStart + 1
EndIf
; Indiquer le début de la coloration style #Style_HTML_Keyword
; Indiquer la position de débug et fin de la coloration
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_HTML_Keyword)
ScintillaSendMessage(gadget, #SCI_INDICATORCLEARRANGE, originalTagStart, upperTag - originalTagStart)
; Coloration de la balise "<" - position de début sur une longueur de 1
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, lowerTag, 1)
; Coloration de "/" si balise fermante - position de début sur une longueur de 1
If isClosing
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, tagStart, 1)
EndIf
; Coloration du nom de balise (ouvrante OU fermante) - Exemple html
If IsKeyword(tagName, keyWords)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, nameStart, tagEnd - nameStart)
EndIf
; Coloration de ">" - position de fin sur une longueur de 1
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, upperTag, 1)
EndIf
;-■ 3 Coloration JavaScript
If IsInsideScriptBlock(gadget, pos)
ColorizeJSStrings(gadget, startPos, endPos)
ColorizeJSComments(gadget, startPos, endPos)
ColorizeJSNumbers(gadget, startPos, endPos)
ColorizeJSKeywords(gadget, startPos, endPos)
ColorizeJSBrackets(gadget, startPos, endPos)
ColorizeJSParentheses(gadget, startPos, endPos)
EndIf
; AU suivant ...
pos = upperTag + 1
Wend
EndProcedure
; Chercher la fin d'un commentaire
Procedure SkipJSLineComment(gadget, pos)
Protected ch
While pos < ScintillaSendMessage(gadget, #SCI_GETLENGTH, 0, 0)
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If ch = 10 Or ch = 13
Break
EndIf
pos + 1
Wend
ProcedureReturn pos
EndProcedure
; Ignorer les blocks de commentaires JavaScript "/* ... */"
Procedure SkipJSBlockComment(gadget, pos)
pos + 2
While pos < ScintillaSendMessage(gadget, #SCI_GETLENGTH, 0, 0) - 1
If ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0) = '*' And
ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '/'
pos + 2
Break
EndIf
pos + 1
Wend
ProcedureReturn pos
EndProcedure
; Colorer les mots clés JavaScript
Procedure ColorizeJSKeywords(gadget, startPos, endPos)
Protected pos = startPos
Protected wordStart, wordEnd, word.s
Protected ch
; Reset de la coloration des mots clés JavaScript
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_KeyWord, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORCLEARRANGE, startPos, endPos - startPos)
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
; Ignorer les lignes de commentaires JavaScript "//"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '/'
pos = SkipJSLineComment(gadget, pos)
Continue
EndIf
; Ignorer les lignes de bloc de commentaires JavaScript "/* ... */"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '*'
pos = SkipJSBlockComment(gadget, pos)
Continue
EndIf
; Sauter non-lettres
If (ch < 'A' Or ch > 'Z') And (ch < 'a' Or ch > 'z') And ch <> '_'
pos + 1
Continue
EndIf
; Lire mot
wordStart = pos
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If (ch >= 'A' And ch <= 'Z') Or (ch >= 'a' And ch <= 'z') Or
(ch >= '0' And ch <= '9') Or ch = '_'
pos + 1
Else
Break
EndIf
Wend
wordEnd = pos
word = GetScintillaWord(gadget, wordStart, wordEnd)
If IsKeyword(word, jsKeywords)
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_KeyWord, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, wordStart, wordEnd - wordStart)
EndIf
Wend
EndProcedure
Procedure ColorizeJSComments(gadget, startPos, endPos)
Protected pos = startPos
Protected ch, nextCh
Protected commentStart, commentEnd
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Comment, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORCLEARRANGE, startPos, endPos - startPos)
While pos < endPos - 1
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
nextCh = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0)
; // commentaire ligne
If ch = '/' And nextCh = '/'
commentStart = pos
; aller jusqu'à fin de ligne ou fin zone
pos + 2
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If ch = 10 Or ch = 13 ; LF ou CR
Break
EndIf
pos + 1
Wend
commentEnd = pos
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Comment, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, commentStart, commentEnd - commentStart)
Continue
EndIf
; /* commentaire bloc */
If ch = '/' And nextCh = '*'
commentStart = pos
pos + 2
While pos < endPos - 1
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
nextCh = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0)
If ch = '*' And nextCh = '/'
pos + 2
Break
EndIf
pos + 1
Wend
commentEnd = pos
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Comment, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, commentStart, commentEnd - commentStart)
Continue
EndIf
pos + 1
Wend
EndProcedure
Procedure ColorizeJSNumbers(gadget, startPos, endPos)
Protected pos = startPos
Protected ch, nextCh
Protected numberStart
Protected hasDot, hasExp
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
; Ignorer les lignes de commentaires JavaScript "//"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '/'
pos = SkipJSLineComment(gadget, pos)
Continue
EndIf
; Ignorer les lignes de bloc de commentaires JavaScript "/* ... */"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '*'
pos = SkipJSBlockComment(gadget, pos)
Continue
EndIf
; Début possible de nombre
If (ch >= '0' And ch <= '9') Or
(ch = '.' And (ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) >= '0' And
ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) <= '9'))
numberStart = pos
hasDot = #False
hasExp = #False
; hex / bin / oct
If ch = '0'
nextCh = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0)
If nextCh = 'x' Or nextCh = 'X' Or nextCh = 'b' Or nextCh = 'B' Or nextCh = 'o' Or nextCh = 'O'
pos + 2
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If (ch >= '0' And ch <= '9') Or
(ch >= 'a' And ch <= 'f') Or
(ch >= 'A' And ch <= 'F')
pos + 1
Else
Break
EndIf
Wend
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Number, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, numberStart, pos - numberStart)
Continue
EndIf
EndIf
; Décimal / flottant / scientifique
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If ch >= '0' And ch <= '9'
pos + 1
Continue
EndIf
If ch = '.' And hasDot = #False
hasDot = #True
pos + 1
Continue
EndIf
If (ch = 'e' Or ch = 'E') And hasExp = #False
hasExp = #True
pos + 1
; Signe optionnel après e
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If ch = '+' Or ch = '-'
pos + 1
EndIf
Continue
EndIf
Break
Wend
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Number, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, numberStart, pos - numberStart)
Continue
EndIf
pos + 1
Wend
EndProcedure
Procedure ColorizeJSStrings(gadget, startPos, endPos)
Protected pos = startPos
Protected ch, quote
Protected stringStart, stringEnd
Protected escaped
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
; Ignorer les lignes de commentaires JavaScript "//"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '/'
pos = SkipJSLineComment(gadget, pos)
Continue
EndIf
; Ignorer les lignes de bloc de commentaires JavaScript "/* ... */"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '*'
pos = SkipJSBlockComment(gadget, pos)
Continue
EndIf
; Détecter début des string : caractére " ou ' `
If ch = 34 Or ch = 39 Or ch = 96
quote = ch
stringStart = pos
pos + 1
escaped = #False
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If escaped
escaped = #False
pos + 1
Continue
EndIf
If ch = 92 ; backslash \
escaped = #True
pos + 1
Continue
EndIf
; fermeture string
If ch = quote
pos + 1
Break
EndIf
pos + 1
Wend
stringEnd = pos
; Coloration du string
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_String, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, stringStart, stringEnd - stringStart)
Continue
EndIf
pos + 1
Wend
EndProcedure
; Coloration des brackets '{' '}' '[' ']'
Procedure ColorizeJSBrackets(gadget, startPos, endPos)
Protected pos, ch
For pos = startPos To endPos - 1
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If ch = '{' Or ch = '}' Or ch = '[' Or ch = ']'
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Bracket)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, pos, 1)
EndIf
Next
EndProcedure
; Coloration des parenthéses
Procedure ColorizeJSParentheses(gadget, startPos, endPos)
Protected pos = startPos
Protected ch
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
; Ignorer les lignes de commentaires JavaScript "//"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '/'
pos = SkipJSLineComment(gadget, pos)
Continue
EndIf
; Ignorer les lignes de bloc de commentaires JavaScript "/* ... */"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '*'
pos = SkipJSBlockComment(gadget, pos)
Continue
EndIf
If ch = '(' Or ch = ')'
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_JS_Parentheses, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, pos, 1)
EndIf
pos + 1
Wend
EndProcedure
;-
; Mettre à jour le folding (Pliage/Dépliage)
Procedure UpdateHTMLFolding(gadget, KeywordsFolding.s)
Protected lineCount, i
Protected level = 0
Protected text.s
Protected buffer.s
; Traitement du pliage/depliage
; Ligne par ligne depuis la premiére ligne
; Obtenir le nombre de lignes
lineCount = ScintillaSendMessage(gadget, #SCI_GETLINECOUNT, 0, 0)
; Parcourir les lignes
For i = 0 To lineCount - 1
; Obtenir le texte de la ligne
text = GetScintillaLineText(gadget, i)
; Important : Supprimer #CRLF$
text = Trim(RemoveString(text, #CRLF$))
; Supprimer les chaines entourant le déclencheur de folding
; Exemples "<html>" -> html ou "</html>" -> html
buffer = RemoveString(text, "<")
buffer = RemoveString(buffer, ">")
buffer = RemoveString(buffer, "/")
; Supprimer les espaces encadrant le texte
buffer = Trim(buffer)
; Traitement balise de fermeture, on décremente aprés
If Bool(Left(text, 2) = "</" And isFoldingKeyWord(buffer, KeywordsFolding))
ScintillaSendMessage(gadget, #SCI_SETFOLDLEVEL, i, #SC_FOLDLEVELBASE + level)
level - 1
If level < 0 : level = 0 : EndIf
Continue
EndIf
; Niveau normal
ScintillaSendMessage(gadget, #SCI_SETFOLDLEVEL, i, #SC_FOLDLEVELBASE + level)
; Traitement balise ouvrante
If Bool(Left(text, 1) = "<" And Mid(text, 2, 1) <> "/" And Right(text, 1)=">" And isFoldingKeyWord(buffer, KeywordsFolding))
ScintillaSendMessage(gadget, #SCI_SETFOLDLEVEL, i, #SC_FOLDLEVELBASE + level | #SC_FOLDLEVELHEADERFLAG)
level + 1
EndIf
Next
EndProcedure
;- CSS
; Retourne les positions de début et fin du code CSS
Procedure GetCSSRange(gadget, *start.Integer, *end.Integer)
Protected textLen = ScintillaSendMessage(gadget, #SCI_GETLENGTH, 0, 0)
Protected pos = 0
Protected inStyle = #False
Protected cssStart = -1
Protected cssEnd = -1
Protected word.s
While pos < textLen
If ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0) = '<'
word = LCase(GetScintillaWord(gadget, pos + 1, pos + 20))
If FindString(word, "style") And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) <> '/'
inStyle = #True
cssStart = pos
; avancer après >
While pos < textLen And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0) <> '>'
pos + 1
Wend
cssStart = pos + 1
EndIf
If FindString(word, "/style")
cssEnd = pos
*start\i = cssStart
*end\i = cssEnd
ProcedureReturn
EndIf
EndIf
pos + 1
Wend
*start\i = -1
*end\i = -1
EndProcedure
; Colorater les mots clés CSS
Procedure ColorizeCSS(gadget, startPos, endPos)
Protected pos = startPos
Protected ch, start, word.s
Protected inSelector = #True
Protected inBlock = #False
Protected commentEnd
Protected quote
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
; Commentaire CSS
; Recherche début de commentaire CSS "/*"
If ch = '/' And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos + 1, 0) = '*'
ScintillaSendMessage(gadget, #SCI_SETTARGETSTART, pos + 2)
ScintillaSendMessage(gadget, #SCI_SETTARGETEND, endPos)
; Recherche fin de commentaire CSS "*/
commentEnd = ScintillaSendMessage(gadget, #SCI_SEARCHINTARGET, 2, commentCSSEndPattern)
If commentEnd = -1
commentEnd = endPos
Else
commentEnd + 2
EndIf
; Invocation du style commentaire et coloration
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_Comment)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, pos, commentEnd - pos)
pos = commentEnd
Continue
EndIf
; String CSS
If ch = 34 Or ch = 39 ; tester " ou '
quote = ch
start = pos
pos + 1
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
; fermeture non échappée
If ch = quote And ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos - 1, 0) <> 92
pos + 1
Break
EndIf
pos + 1
Wend
; Invocation du style sting et coloration
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_String, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, start, pos - start)
Continue
EndIf
; Accolades / ponctuation
If ch = '{' Or ch = '}' Or ch = ':' Or ch = ';'
; Invocation du style punctuation et coloration
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_Punct, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, pos, 1)
If ch = '{'
inBlock = #True
inSelector = #False
ElseIf ch = '}'
inBlock = #False
inSelector = #True
EndIf
pos + 1
Continue
EndIf
; Nombre CSS
If (ch >= '0' And ch <= '9')
start = pos
pos + 1
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If Not ((ch >= '0' And ch <= '9') Or ch = '.' Or ch = '%' Or (ch >= 'a' And ch <= 'z'))
Break
EndIf
pos + 1
Wend
; Invocation du style nombre et coloration
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_Number, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, start, pos - start)
Continue
EndIf
; Identifiant CSS
If (ch >= 'a' And ch <= 'z') Or (ch >= 'A' And ch <= 'Z') Or ch = '.' Or ch = '#'
start = pos
pos + 1
While pos < endPos
ch = ScintillaSendMessage(gadget, #SCI_GETCHARAT, pos, 0)
If Not ((ch >= 'a' And ch <= 'z') Or (ch >= 'A' And ch <= 'Z') Or ch = '-' Or (ch >= '0' And ch <= '9'))
Break
EndIf
pos + 1
Wend
word = LCase(GetScintillaWord(gadget, start, pos))
If inSelector
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_Selector, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, start, pos - start)
Else
If isKeyword(word, cssProperties)
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_Property, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, start, pos - start)
ElseIf iskeyword(word, cssvalues)
ScintillaSendMessage(gadget, #SCI_SETINDICATORCURRENT, #Style_CSS_Value, 0)
ScintillaSendMessage(gadget, #SCI_INDICATORFILLRANGE, start, pos - start)
EndIf
EndIf
Continue
EndIf
pos + 1
Wend
EndProcedure
;-
;- Utilitaire(s)
; Obtenir un UTF8 d'un string
Procedure MakeUTF8Text(text.s)
Static buffer.s
buffer = Space(StringByteLength(text, #PB_UTF8) + 1)
PokeS(@buffer, text, -1, #PB_UTF8)
ProcedureReturn @buffer
EndProcedure
J'ai d'autres idées à mettre en œuvres comme le match des parenthèses et des brackets.
Quand on sélectionne une parenthèse, celle-ci est mise en valeur par une coloration spécifique ainsi que la parenthèse fermente.
Il en serait de même pour les brackets "{'" ... "}" et les crochets "[" ... "]"
Mais je vais m'arrêter là pour ce sujet. Le code commence à être lourd à digérer