Scintilla + Fold (?)
Posted: Sun Mar 03, 2024 4:27 am
I want to do a text search in files and output the found lines.
I found an example of folding and made a few changes.
1. I couldn't make the black color for the folding field.
2. I need to remove the possibility of a folding level, since only one level is needed.
3. The line containing the path must be highlighted the entire path. But I can do this on my own.
4. I had to use the "}" character at the end of the text block, but I would like to get rid of the extra line and the extra character, especially since it can be in the search text. I assume that if a line does not start with a tab, then this is the beginning of folding, and the end of folding is a new line without tabs. That is, the row simultaneously closes the previous one and opens a new one.
I found an example of folding and made a few changes.
1. I couldn't make the black color for the folding field.
2. I need to remove the possibility of a folding level, since only one level is needed.
3. The line containing the path must be highlighted the entire path. But I can do this on my own.
4. I had to use the "}" character at the end of the text block, but I would like to get rid of the extra line and the extra character, especially since it can be in the search text. I assume that if a line does not start with a tab, then this is the beginning of folding, and the end of folding is a new line without tabs. That is, the row simultaneously closes the previous one and opens a new one.
Code: Select all
; https://www.purebasic.fr/english/viewtopic.php?t=68066
If Not InitScintilla()
MessageRequester("", "Failed to initialize Scintilla")
End
EndIf
#indicator_Find = 0
; Эти константы будут использоватся для подсветки синтаксиса.
Enumeration 0
#LS_Space
#LS_Comment
#LS_Keyword
#LS_FoldKeyword
EndEnumeration
Procedure MyLexerInit()
Protected *buffer
; Шрифт
*buffer = UTF8("consolas")
ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, *buffer)
FreeMemory(*buffer)
; Размер шрифта
ScintillaSendMessage(0, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 12)
ScintillaSendMessage(0, #SCI_STYLECLEARALL)
; Цвет активной строки
ScintillaSendMessage(0, #SCI_SETCARETLINEBACK, 0)
; Разрешаем отмечать активную строку
ScintillaSendMessage(0, #SCI_SETCARETLINEVISIBLE, #True)
; Чёрный фон
ScintillaSendMessage(0, #SCI_STYLESETBACK, #STYLE_DEFAULT, $3F3F3F); цвет фона
Protected i
For i = 0 To 3
ScintillaSendMessage(0, #SCI_STYLESETBACK, i, $3F3F3F) ; цвет фона
; ScintillaSendMessage(0, #SCI_STYLESETFORE, i, $AAAAAA) ; цвет текста
Next
ScintillaSendMessage(0, #SCI_SETCARETFORE, $FFFFFF) ; цвет текстовго курсора
ScintillaSendMessage(0, #SCI_SETSELBACK, 1, $a0a0a0) ; цвет фона выделения
ScintillaSendMessage(0, #SCI_SETSELALPHA, 100) ; прозрачность выделения
ScintillaSendMessage(0, #SCI_SETCONTROLCHARSYMBOL, 1) ; символы менее 32
ScintillaSendMessage(0, #SCI_STYLESETBACK, #STYLE_LINENUMBER, $222222)
ScintillaSendMessage(0, #SCI_STYLESETFORE, #STYLE_LINENUMBER, $AAAAAA)
; Устанавливаем цвета для подсветки синтаксиса
; Эти цвета условно присваиваются константам #LexerState_...
ScintillaSendMessage(0, #SCI_STYLESETFORE, #LS_Comment, $71AE71) ; Цвет комментариев
ScintillaSendMessage(0, #SCI_STYLESETITALIC, #LS_Comment, 1) ; Выделять комментарии наклонным шрифтом
ScintillaSendMessage(0, #SCI_STYLESETFORE, #LS_Keyword, $AAAAAA); Цвет обычного текста
ScintillaSendMessage(0, #SCI_STYLESETFORE, #LS_FoldKeyword, $FF9900) ; Цвет ключевых слов.
; Margins
ScintillaSendMessage(0, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER) ; Добавляем поле автонумерации
; ScintillaSendMessage(0, #SCI_SETMARGINTYPEN, #STYLE_LINENUMBER, 0) ; удалить
ScintillaSendMessage(0, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS); Добавляем поле для свертки и маркеров
; ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 0, 20) ; Ширина поля автонумирации
*buffer = UTF8("_999")
marginWidth = ScintillaSendMessage(0, #SCI_TEXTWIDTH, #STYLE_LINENUMBER, *buffer)
FreeMemory(*buffer)
ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 0, marginWidth) ; Устанавливает ширину поля номеров строк
ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 2, 20); Ширина поля свертки и маркеров
ScintillaSendMessage(0, #SCI_SETMARGINSENSITIVEN, 2, #True) ; поле ловит событие клика мыши, без него свёртка не работает
; Иконки свёртки текста
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDER, #SC_MARK_BOXPLUS)
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_BOXMINUS)
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERSUB, #SC_MARK_VLINE)
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERTAIL, #SC_MARK_LCORNERCURVE)
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEREND, #SC_MARK_BOXPLUSCONNECTED)
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPENMID, #SC_MARK_BOXMINUSCONNECTED)
ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERMIDTAIL, #SC_MARK_TCORNERCURVE)
; Выберите цвет значка свёрток
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDER, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDER, $FF)
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, $FF)
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPENMID, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPENMID, $AA00)
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEREND, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEREND, $AA00)
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDERMIDTAIL, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERMIDTAIL, 0)
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDERSUB, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERSUB, 0)
ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDERTAIL, $FFFFFF)
ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERTAIL, 0)
; #SC_MASK_FOLDERS залитое
; #SC_MARK_PLUS без каймы
; #SC_MARK_MINUS без каймы
ScintillaSendMessage(0, #SCI_INDICSETSTYLE, #indicator_Find, #INDIC_TEXTFORE) ; индикатор
ScintillaSendMessage(0, #SCI_INDICSETFORE, #indicator_Find, $8080FF) ; красный
ScintillaSendMessage(0, #SCI_INDICSETUNDER, #indicator_Find, 1) ; индикатор под текстом, т.е. не затеняет его
ScintillaSendMessage(0, #SCI_INDICSETALPHA, #indicator_Find, 127) ; Transparency
EndProcedure
; code = \nmhdr\code
; pos = \Position
; ch = \ch
; modificationType = \modifiers
; text = \text
; Length = \length
; linesAdded = \linesAdded
; message = \message
; wParam = \wParam
; lParam = \lParam
; line = \line
; foldLevelNow = \foldLevelNow
; foldLevelPrev = \foldLevelPrev
; margin = \margin
; listType = \listType
; x = \x
; y = \y
ProcedureDLL ScintillaCallBack(Gadget, *scinotify.SCNotification) ; Обработка событий от редактора
With *scinotify.SCNotification
Select \nmhdr\code
Case #SCN_MARGINCLICK ; Клик по полям редаткора слева
; обновление свёртки
linenumber = ScintillaSendMessage(0, #SCI_LINEFROMPOSITION, \Position ) ; Узнаём номер строки
Select \margin
Case 2 ; Если был щелчёк пополю свёртки текста, своравиваем или разворачиваем его
ScintillaSendMessage(0, #SCI_TOGGLEFOLD, linenumber)
EndSelect
Case #SCN_STYLENEEDED ; событие о необходимости подсветки (открытие документа, вставка/уделение, ввод символа)
EndStyledPos = ScintillaSendMessage(0, #SCI_GETENDSTYLED) ; Позиция, от которого необходима подсветка.
linenumber = ScintillaSendMessage(0, #SCI_LINEFROMPOSITION, EndStyledPos) ; номер строки из позиции.
If linenumber = 0
level = #SC_FOLDLEVELBASE
Else
linenumber - 1
; получаем уровень вложенности свёртки
level = ScintillaSendMessage(0, #SCI_GETFOLDLEVEL, linenumber) & ~ #SC_FOLDLEVELHEADERFLAG
EndIf
thislevel = level
nextlevel = level
CurrentPos.l = ScintillaSendMessage(0, #SCI_POSITIONFROMLINE, linenumber) ; позиция начала указанной строки.
ScintillaSendMessage(0, #SCI_STARTSTYLING, CurrentPos, $1F | #INDICS_MASK); Вызвать подкрашивание. Последний параметр не используется
State = #LS_Space
KeywordStartPos = CurrentPos
keyword.s = ""
While CurrentPos <= \Position
OldState = State ; запоминаем последний тип
Char.l = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos) ; Получаем символ из текущей позиции курсора.
If Char = #LF Or Char = #CR
State = #LS_Space
Else
If Char = #TAB Or Char = ' ' Or Char = '.'
State = #LS_Space
Else
State = #LS_Keyword
keyword + Chr(Char)
EndIf
EndIf
If OldState <> State Or CurrentPos = \Position
If OldState = #LS_Keyword
lkeyword.s = keyword
If Asc(lkeyword) >= '0' And Asc(lkeyword) <= '9'
; If lkeyword = "1" Or lkeyword = "2"
thislevel | #SC_FOLDLEVELHEADERFLAG ; указывает, что линия является заголовком ???
nextlevel + 1
OldState = #LS_FoldKeyword
ElseIf lkeyword = "}"
nextlevel - 1
If nextlevel < #SC_FOLDLEVELBASE
nextlevel = #SC_FOLDLEVELBASE
EndIf
OldState = #LS_FoldKeyword
EndIf
keyword = ""
EndIf
ScintillaSendMessage(0, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState) ; Вроде как подсвечивание синтаксиса. Или только подготовка к этому ???
KeywordStartPos = CurrentPos
EndIf
If Char = #LF Or CurrentPos = \Position
ScintillaSendMessage(0, #SCI_SETFOLDLEVEL, linenumber, thislevel) ; Кажется за свёртку отвечает.
thislevel = nextlevel
linenumber + 1
EndIf
CurrentPos + 1
Wend
EndSelect
EndWith
EndProcedure
Procedure SizeHandler()
ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 4, WindowHeight(0) - 2)
EndProcedure
;-┌──GUI──┐
If OpenWindow(0, 0, 0, 602, 602, "Static Scintilla Example", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
ButtonGadget(1, 2, 2, 130, 25, "Switch all folds")
; ButtonGadget(2, 32, 2, 28, 25, "v")
; Создаём гаджет и прогедуре ScintillaCallBack() присваиваем статус обработчика событий редактора.
ScintillaGadget(0, 2, 32, 598, 568, @ScintillaCallBack())
MyLexerInit() ; Настраиваем редактор
; Установите какой-нибудь пример текста
For i = 1 To 8
Text$ + Str(i) + ". C:\PB\" + Str(i) + ".txt" + #CRLF$
For j = 1 To Random(5, 1)
Text$ + " Hello guys how are you" + #CRLF$
Next
; Text$ + "}" + #CRLF$
Text$ + "}" + #CRLF$
Next
*Text = UTF8(Text$)
ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Text)
FreeMemory(*Text)
ScintillaSendMessage(0, #SCI_SETINDICATORCURRENT, #indicator_Find, #INDIC_STRAIGHTBOX) ; текущий
SearchStr$ = "how"
length = Len(SearchStr$)
Repeat
pos = FindString(Text$, SearchStr$, pos + 1, #PB_String_NoCase)
If pos
ScintillaSendMessage(0, #SCI_INDICATORFILLRANGE, pos - 1, length) ; подсветить диапазон
EndIf
Until Not pos
BindEvent(#PB_Event_SizeWindow, @SizeHandler())
;-┌──Loop──┐
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case 1
ScintillaSendMessage(0, #SCI_FOLDALL, #SC_FOLDACTION_TOGGLE)
; Case 2
; Debug 1
EndSelect
Case #PB_Event_CloseWindow
CloseWindow(0)
End
EndSelect
ForEver
EndIf