Scintilla + Fold (?)

Just starting out? Need help? Post your questions and find answers here.
AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Scintilla + Fold (?)

Post by AZJIO »

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.

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

AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Scintilla + Fold (?)

Post by AZJIO »

Since I am interested in outputting information and not editing, I did the processing 1 time. I noticed that when scrolling text, the callback function received information about the need for highlighting and this created significant delays when outputting 3000 lines. So I did code highlighting once.

When improving, I used the luck method. That is, substitute the values ​​and expect that it will probably work. I don’t know how this idiom is written in English, but in Russian it sounds like “the poke method”.

Previously I found it in 1.6 seconds and then tinted it and that’s why there was a slowdown.
Now, due to the coloring of all the text, it opens in 3.6 seconds. Therefore, I returned the old option, which gives the result in 1.6 seconds.

screenshot

Code: Select all

EnableExplicit
; 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, marginWidth, i
	; Шрифт
	*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); цвет фона
	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, $FFAA66) ; Цвет ключевых слов.

	; 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_ARROW)
	ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_ARROWDOWN)
; 	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, $FF9900)

	ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF)
	ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, $FF9900)

	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


Procedure SetFoldHighlight()
	Protected EndStyledPos, nextlevel, CurrentPos.i, s, linenumber, level, Char.u
	Protected KeywordStartPos, thislevel, State, EndProcedur, keyword.s, OldState, lkeyword.s
	Protected lenAll, flgClose, Char2.u
	Protected Buffer$ ; буферизируем ключ открытия свёртки, чтобы точно идентифицировать по: начало строк + число
	; событие о необходимости подсветки (открытие документа, вставка/уделение, ввод символа)
	EndStyledPos = 0 ; Позиция, от которого необходима подсветка.
	linenumber = 0 ; номер строки из позиции.
	lenAll =  ScintillaSendMessage(0, #SCI_GETLENGTH) 
	
	level = #SC_FOLDLEVELBASE
	
	thislevel = level
	nextlevel = level
	
	CurrentPos = 0
	ScintillaSendMessage(0, #SCI_STARTSTYLING, CurrentPos, $1F | #INDICS_MASK); Вызвать подкрашивание. Последний параметр не используется
	State = #LS_Space
	KeywordStartPos = CurrentPos
	keyword = ""
	
	While CurrentPos <= lenAll ; крутим цикл, пока текущий символ меньше или равен концу документа
		OldState = State ; запоминаем предыдущий тип оставшийся после завершение предыдущего шага цикла
		
; 		от читаемого символа определяем флаг состояния подсветки
		Char.u = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos) ; Получаем код символа из текущей позиции курсора.
		If Char = #LF Or Char = #CR
			; 			если перенос, то сбросить поиск и начать новый анализ строки, если не там то это путь и
			; 			надо закрыть предыдущую свёртку и начать новую
			State = #LS_Space
			
			Char2 = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos + 1)
			If  Char2 >= '0' And Char2 <= '9'
; 			If  Char2 <> #TAB And Char2 <> #CR And Char2 <> #LF
; 				Debug "---------" + Char2
				flgClose = 1
			EndIf
		ElseIf flgClose
			State = #LS_Keyword
			keyword + Chr(Char)
		Else
			If Char = #TAB
				State = #LS_Space
			Else
				State = #LS_Keyword
				keyword + Chr(Char)
; 				Debug "-" + Char
			EndIf
		EndIf
		
		If flgClose
			nextlevel - 1
			If nextlevel < #SC_FOLDLEVELBASE ; если ошибки и два раза закрытие свёртки, то пишем базовый/корневой уровень свёрки
				nextlevel = #SC_FOLDLEVELBASE
			EndIf
			OldState = #LS_FoldKeyword
			flgClose = 0
		EndIf
		
		If OldState <> State Or CurrentPos = lenAll
			If OldState = #LS_Keyword
				lkeyword = keyword
; 				Debug "----" + Asc(lkeyword)
; 				Debug "---------" + Char
				If Asc(lkeyword) >= '0' And Asc(lkeyword) <= '9'
					; 							If lkeyword = "1" Or lkeyword = "2"
					thislevel | #SC_FOLDLEVELHEADERFLAG ; указывает, что линия является элементом открытия свёртки
					nextlevel + 1
					OldState = #LS_FoldKeyword ; сохраняем флаг для следующего шага цикла
				EndIf
				keyword = ""
			EndIf
			; подсвечивание синтаксиса, длина и флаг стиля.
			ScintillaSendMessage(0, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState)
			KeywordStartPos = CurrentPos
		EndIf
		
		If Char = #LF Or CurrentPos = lenAll
			ScintillaSendMessage(0, #SCI_SETFOLDLEVEL, linenumber, thislevel) ; заканчивает уровень свёртки на переносе или на конце строки
			thislevel = nextlevel
			linenumber + 1
		EndIf
		
		CurrentPos + 1
	Wend
	
EndProcedure

; так как у нас нередактируемый по факту гадже, а предназначен только для вывода информации, то
; обрабатываем подсветку один раз при вставке кода, но не в коем случае не в условиях прокрутки

ProcedureDLL ScintillaCallBack(Gadget, *scinotify.SCNotification) ; Обработка событий от редактора
	Protected linenumber

	With *scinotify.SCNotification
		Select \nmhdr\code
			Case #SCN_MARGINCLICK ; Клик по полям редаткора слева
				; обновление свёртки
				linenumber = ScintillaSendMessage(0, #SCI_LINEFROMPOSITION, \Position ) ; Узнаём номер строки, в которой клик
				Select \margin
					Case 2 ; Если был клик по полю "2" - свёртки текста, своравиваем или разворачиваем его
						ScintillaSendMessage(0, #SCI_TOGGLEFOLD, linenumber)
				EndSelect
		EndSelect
	EndWith
EndProcedure

Procedure SizeHandler()
	ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 4, WindowHeight(0) - 2)
EndProcedure

Define Text$, *Text, i, j, SearchStr$, length, pos

;-┌──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() ; Настраиваем редактор

	; Установите какой-нибудь пример текста
	Text$ = #CRLF$
	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
	Next
	Text$ = Left(Text$, Len(Text$) - 2)
	*Text = UTF8(Text$)
	ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Text)
	FreeMemory(*Text)
	
	SetFoldHighlight()
	
	
	ScintillaSendMessage(0, #SCI_SETINDICATORCURRENT, #indicator_Find) ; текущий
	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

Code: Select all

EnableExplicit
; 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, marginWidth
	; Шрифт
	*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_ARROW)
	ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_ARROWDOWN)
; 	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, $FF9900)

	ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF)
	ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, $FF9900)

	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) ; Обработка событий от редактора
	Protected EndStyledPos, nextlevel, CurrentPos.i, s, linenumber, level, Char.u
	Protected KeywordStartPos, thislevel, State, EndProcedur, keyword.s, OldState, lkeyword.s
	Protected lenAll, flgClose, Char2.u
	Protected Buffer$ ; буферизируем ключ открытия свёртки, чтобы точно идентифицировать по: начало строк + число

	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 = ScintillaSendMessage(0, #SCI_POSITIONFROMLINE, linenumber) ; позиция начала указанной строки.
				ScintillaSendMessage(0, #SCI_STARTSTYLING, CurrentPos, $1F | #INDICS_MASK); Вызвать подкрашивание. Последний параметр не используется
				State = #LS_Space
				KeywordStartPos = CurrentPos
				keyword = ""

				While CurrentPos <= \Position
					OldState = State ; запоминаем последний тип

					; 		от читаемого символа определяем флаг состояния подсветки
					Char.u = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos) ; Получаем код символа из текущей позиции курсора.
					If Char = #LF Or Char = #CR
						; 			если перенос, то сбросить поиск и начать новый анализ строки, если не там то это путь и
						; 			надо закрыть предыдущую свёртку и начать новую
						State = #LS_Space
						
						Char2 = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos + 1)
						If  Char2 >= '0' And Char2 <= '9'
							; 			If  Char2 <> #TAB And Char2 <> #CR And Char2 <> #LF
							; 				Debug "---------" + Char2
							flgClose = 1
						EndIf
					ElseIf flgClose
						State = #LS_Keyword
						keyword + Chr(Char)
					Else
						If Char = #TAB
							State = #LS_Space
						Else
							State = #LS_Keyword
							keyword + Chr(Char)
							; 				Debug "-" + Char
						EndIf
					EndIf
		
					If flgClose
						nextlevel - 1
						If nextlevel < #SC_FOLDLEVELBASE ; если ошибки и два раза закрытие свёртки, то пишем базовый/корневой уровень свёрки
							nextlevel = #SC_FOLDLEVELBASE
						EndIf
						OldState = #LS_FoldKeyword
						flgClose = 0
					EndIf

					If OldState <> State Or CurrentPos = \Position
						If OldState = #LS_Keyword
							lkeyword = keyword
							If Asc(lkeyword) >= '0' And Asc(lkeyword) <= '9'
; 							If lkeyword = "1" Or lkeyword = "2"
								thislevel | #SC_FOLDLEVELHEADERFLAG ; указывает, что линия является заголовком ???
								nextlevel + 1
								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

Define Text$, *Text, i, j, SearchStr$, length, pos

;-┌──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
	Next
	Text$ = Left(Text$, Len(Text$) - 2)
	*Text = UTF8(Text$)
	ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Text)
	FreeMemory(*Text)
	
	
	ScintillaSendMessage(0, #SCI_SETINDICATORCURRENT, #indicator_Find) ; текущий
	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

AZJIO
Addict
Addict
Posts: 2143
Joined: Sun May 14, 2017 1:48 am

Re: Scintilla + Fold (?)

Post by AZJIO »

In an artificial example, it works fine, but in real output results, folding and highlighting break due to imperfections in the code. No matter what crutches I come up with, I cannot eliminate all the problems.

Code: Select all

EnableExplicit
; 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_Keyword
	#LS_FoldKeyword
EndEnumeration

Procedure MyLexerInit()
	Protected *buffer, marginWidth
	; Шрифт
	*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_Keyword, $AAAAAA); Цвет обычного текста
	ScintillaSendMessage(0, #SCI_STYLESETFORE, #LS_FoldKeyword, $FF9900) ; Цвет ключевых слов.

	; Margins
	ScintillaSendMessage(0, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER) ; Добавляем поле автонумерации
	ScintillaSendMessage(0, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS); Добавляем поле для свертки и маркеров
	*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_ARROW)
	ScintillaSendMessage(0, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_ARROWDOWN)
; 	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, $FF9900)

	ScintillaSendMessage(0, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF)
	ScintillaSendMessage(0, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, $FF9900)

	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

ProcedureDLL ScintillaCallBack(Gadget, *scinotify.SCNotification) ; Обработка событий от редактора
	Protected EndStyledPos, nextlevel, CurrentPos.i, s, linenumber, level, Char.u;, CharOld.u
	Protected KeywordStartPos, thislevel, State, EndProcedur, keyword, OldState
	Protected lenAll, flgClose, Char2.u, tmp
	Protected Buffer$ ; буферизируем ключ открытия свёртки, чтобы точно идентифицировать по: начало строк + число

	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 = ScintillaSendMessage(0, #SCI_POSITIONFROMLINE, linenumber) ; позиция начала указанной строки.
				ScintillaSendMessage(0, #SCI_STARTSTYLING, CurrentPos, $1F | #INDICS_MASK); Вызвать подкрашивание. Последний параметр не используется
				State = #LS_Space
				KeywordStartPos = CurrentPos
				keyword = 0

				While CurrentPos <= \Position
					OldState = State ; запоминаем последний тип

					; 		от читаемого символа определяем флаг состояния подсветки
					Char = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos) ; Получаем код символа из текущей позиции курсора.
					Select Char
						Case #CR, #LF
							State = #LS_Space
							Char2 = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos + 1)
							If Char2 >= '0' And Char2 <= '9'
								flgClose = 1
							EndIf
						Case #TAB
							State = #LS_Space
							CurrentPos + 2
							Continue
						Default
							State = #LS_Keyword
							If Not keyword
								keyword = Char
							EndIf
					EndSelect


					If flgClose
						nextlevel - 1
						If nextlevel < #SC_FOLDLEVELBASE ; если ошибки и два раза закрытие свёртки, то пишем базовый/корневой уровень свёртки
							nextlevel = #SC_FOLDLEVELBASE
						EndIf
						OldState = #LS_FoldKeyword
						flgClose = 0
					EndIf

					If OldState <> State Or CurrentPos = \Position
						If OldState = #LS_Keyword
							If keyword >= '0' And keyword <= '9'
; 							If lkeyword = "1" Or lkeyword = "2"
								thislevel | #SC_FOLDLEVELHEADERFLAG ; указывает, что линия является элементом открытия свёртки
								nextlevel + 1
								OldState = #LS_FoldKeyword
							EndIf
							keyword = 0
						EndIf
						; Подсветка накопленных символов в момент переключения типа лексемы

						tmp = ScintillaSendMessage(0, #SCI_LINEFROMPOSITION, \Position)
						tmp = ScintillaSendMessage(0, #SCI_POSITIONFROMLINE, tmp) ; позиция начала указанной строки.
; 						Debug CurrentPos
; 						Debug tmp
						If tmp = \Position
							ScintillaSendMessage(0, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState)
							KeywordStartPos = CurrentPos ; обновляем позицию KeywordStartPos как старта новой подсветки
						EndIf
					EndIf

					If Char = #LF Or CurrentPos = \Position
						; заканчивает уровень свёртки на переносе или на конце строки
						ScintillaSendMessage(0, #SCI_SETFOLDLEVEL, linenumber, thislevel)
						thislevel = nextlevel
						linenumber + 1
					EndIf

; 					CharOld = Char
					CurrentPos + 1
				Wend

		EndSelect
	EndWith
EndProcedure

Procedure SizeHandler()
	ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 4, WindowHeight(0) - 2)
EndProcedure

Define Text$, *Text, i, j, SearchStr$, length, pos

;-┌──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")
	; Создаём гаджет и прогедуре 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(7, 3)
			Text$ + "	1Hello guys how are you1" + #CRLF$
		Next
	Next
	Text$ = Left(Text$, Len(Text$) - 2)
	*Text = UTF8(Text$)
	ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Text)
	FreeMemory(*Text)


	ScintillaSendMessage(0, #SCI_SETINDICATORCURRENT, #indicator_Find) ; текущий
	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
Post Reply