Page 1 of 1

How to highlight a word in the IDE?

Posted: Sun Jul 28, 2024 1:26 pm
by AZJIO
This code highlights the text. But I can’t highlight the word (comment out the penultimate line).

Code: Select all

Global SelectedWord.s
Global PbIdeHandle, ScintillaHandle
Global g_ClassTextIDE.s, g_TitleTextIDE.s
;- ● Declare
Declare.s GetScintillaRangeText(cursor, length)
; ---------------------------------------------------------------------------------------------------------------------

	Global classText.s = Space(256)
; найти окно редактора PureBasic, Notepad++, SciTE
	Procedure.l enumChildren0(hwnd.l)
		If hwnd
			GetClassName_(hwnd, @classText, 256)
			If classText = g_ClassTextIDE
				GetWindowText_(hwnd, @classText, 256)
				; если заголовок не указан, или в нём есть имя редактора, то применить
				If Not Asc(g_TitleTextIDE) Or FindString(classText, g_TitleTextIDE)
					PbIdeHandle = hwnd
					ProcedureReturn 0
				EndIf
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 0
	EndProcedure

; найти Scintilla, для всех трёх редакторов одинаково, так как используются только Scintilla
	Procedure.l enumChildren1(hwnd.l)
		If hwnd
			GetClassName_(hwnd, @classText, 256)
			If classText = "Scintilla"
				ScintillaHandle = hwnd
				ProcedureReturn 0
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 0
	EndProcedure

	Procedure GetWord()
		Protected tmp, WordStart, WordEnd
		tmp = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		SendMessage_(ScintillaHandle, #SCI_WORDLEFT, 0, 0)
		WordStart = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		; Debug WordStart
		SendMessage_(ScintillaHandle, #SCI_WORDRIGHT, 0, 0)
		WordEnd = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		; Debug WordEnd
		SendMessage_(ScintillaHandle, #SCI_SETCURRENTPOS, tmp, 0)
		SendMessage_(ScintillaHandle, #SCI_SETANCHOR, tmp, 0)
		SelectedWord = GetScintillaRangeText(WordStart, WordEnd - WordStart)
		; Debug "|" + SelectedWord + "|"
	EndProcedure

Procedure.s GetScintillaRangeText(cursor, length)
	Protected ReturnValue.s
; 	Protected length
	Protected *buffer
	Protected processId
	Protected hProcess
	Protected result

	If length
		*buffer = AllocateMemory(length + 2)
		If *buffer
			SendMessageTimeout_(ScintillaHandle, #SCI_GETRANGEPOINTER, cursor, 0, #SMTO_ABORTIFHUNG, 2000, @result)
			If result
				GetWindowThreadProcessId_(ScintillaHandle, @processId)
				hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, processId)
				If hProcess
					ReadProcessMemory_(hProcess, result, *buffer, length, 0)
					ReturnValue = PeekS(*buffer, -1, #PB_UTF8)
					CloseHandle_(hProcess)
				EndIf
			EndIf
		EndIf
		FreeMemory(*buffer)
	EndIf
	ProcedureReturn ReturnValue
EndProcedure


Procedure Initialization()
	Protected Anchor, Cursor, LenSel, rex1, SelectedWord2.s, CountParam
	Protected Text.string
; g_ClassTextIDE
; g_TitleTextIDE

	; 	Если переданы параметры, то получить доступ через них.
	CountParam = CountProgramParameters()
	If CountParam > 1
; 		Первые 2 параметра определяют окно с которым работать - класс и заголовок
		g_TitleTextIDE = ProgramParameter(0)
		g_ClassTextIDE = ProgramParameter(1)
		; 		MessageRequester("PathFile$", PathFile$)

		; 		MessageRequester("", SelectedWord + #CRLF$ + Str(CursorLine) + #CRLF$ + PathFile$ + #CRLF$ + NameEditor$)

		EnumChildWindows_(0, @enumChildren0(), 0)
		If CountParam > 3 : MessageRequester("", Str(PbIdeHandle)) : EndIf
		If Not PbIdeHandle : End : EndIf
		EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
		; 		MessageRequester("0", Str(PbIdeHandle) + #CRLF$ + Str(ScintillaHandle))
		If CountParam > 3 : MessageRequester("Scintilla", Str(ScintillaHandle)) : EndIf
		If Not ScintillaHandle : End : EndIf
		
		If CountParam > 2
			SelectedWord = ProgramParameter(2)
		Else
			GetWord()
		EndIf
		If CountParam > 3 : MessageRequester("", SelectedWord) : EndIf

; 		tmp = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
; 		CursorLine = SendMessage_(ScintillaHandle, #SCI_LINEFROMPOSITION, tmp, 0)


		; 		tmp = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)


	Else

		CompilerIf #PB_Compiler_Debugger
			; блок кода только для теста, по нажатию F5
			g_TitleTextIDE = "PureBasic"
			g_ClassTextIDE = "WindowClass_2"
			EnumChildWindows_(0, @enumChildren0(), 0)
			EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
			; конец: блок кода только для теста
		CompilerElse
; 			без пераметров считаем что PureBasic и берём из переменных среды
			PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
			If Not PbIdeHandle : End : EndIf

			ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
			If Not ScintillaHandle : End : EndIf
			SelectedWord = GetEnvironmentVariable("PB_TOOL_Word")
		CompilerEndIf

	EndIf

; так как найдена Scintilla, то пробуем получить выделенный текст
; 	CursorLine = Int(Val(StringField(GetEnvironmentVariable("PB_TOOL_Cursor"), 1, "x")))
; 	MessageRequester("PB_TOOL_Cursor", Str(CursorLine))
	Cursor = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
	Anchor = SendMessage_(ScintillaHandle, #SCI_GETANCHOR, 0, 0)
	If Anchor <> Cursor
		If Anchor < Cursor
			LenSel = Cursor - Anchor
			Cursor = Anchor
		Else
			LenSel = Anchor - Cursor
		EndIf
		SelectedWord2 = GetScintillaRangeText(Cursor, LenSel)
		If FindString(SelectedWord2, #LF$)
			End
		EndIf

		rex1 = CreateRegularExpression(#PB_Any, "\A\w+\z", #PB_RegularExpression_NoCase)
		If Not MatchRegularExpression(rex1, SelectedWord2)
			IsWord = 0
		EndIf
		FreeRegularExpression(rex1)
	EndIf
	CursorLine = SendMessage_(ScintillaHandle, #SCI_LINEFROMPOSITION, Cursor, 0) + 1

; 	Здесь различие между выделенным целым словом и частью слова, чтобы часть слова искать не как целое, без \b
	If Asc(SelectedWord2) And SelectedWord2 <> SelectedWord
		SelectedWord = SelectedWord2
	Else
		IsWord = 1
	EndIf


	CompilerIf #PB_Compiler_Debugger
		If Not Asc(SelectedWord) And CountParam = 0
			GetWord()
		EndIf
	CompilerEndIf
EndProcedure

Initialization()
Debug "Scintilla = " + ScintillaHandle
Debug "SelectedWord = " + SelectedWord

;- RegExp подсветка стандартного текста
Procedure Color(SelectedWord.s, posStart, posEnd)
	Protected txtLen, StartPos, EndPos, firstMatchPos
	Protected len, *mem
; 	SendMessage_(ScintillaHandle, #SCI_SETSEARCHFLAGS, #SCFIND_REGEXP | #SCFIND_POSIX, 0)
	
; 	len2 = Len(SelectedWord)
	len2 = StringByteLength(SelectedWord, #PB_UTF8)
	*mem = UTF8(SelectedWord)
	EndPos = posStart
	Repeat
		SendMessage_(ScintillaHandle, #SCI_SETTARGETSTART, EndPos, 0) ; от начала (задаём область поиска) используя позицию конца предыдущего поиска
		SendMessage_(ScintillaHandle, #SCI_SETTARGETEND, posEnd, 0)	  ; до конца по длине текста
		firstMatchPos = SendMessage_(ScintillaHandle, #SCI_SEARCHINTARGET, len2, *mem) ; возвращает позицию первого найденного. В параметрах длина искомого и указатель
		Debug "Find = " + firstMatchPos
		If firstMatchPos > -1														  ; если больше -1, то есть найдено, то
			StartPos = SendMessage_(ScintillaHandle, #SCI_GETTARGETSTART, 0, 0)		  ; получает позицию начала найденного
			EndPos = SendMessage_(ScintillaHandle, #SCI_GETTARGETEND, 0, 0)			  ; получает позицию конца найденного
; 			SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE, StartPos, EndPos - StartPos) ; начало и длина
			SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE, StartPos, len2) ; начало и длина
;             Debug Str(StartPos) + " " + Str(EndPos) + " " + Str(EndPos - StartPos)
		Else
			Break
		EndIf
	ForEver
	FreeMemory(*mem)
EndProcedure


; #num_indicator = 3
#num_indicator = 13

Define *Text, nLine, start, length

SendMessage_(ScintillaHandle, #SCI_INDICSETSTYLE, #num_indicator, #INDIC_STRAIGHTBOX) ; первый индикатор со стилем 8 (0-19)
SendMessage_(ScintillaHandle, #SCI_INDICSETFORE, #num_indicator, #Red)				  ; первый индикатор с красным цветом
SendMessage_(ScintillaHandle, #SCI_SETINDICATORCURRENT, #num_indicator, #INDIC_STRAIGHTBOX) ; делает индикатор текущим
SendMessage_(ScintillaHandle, #SCI_INDICSETUNDER, #num_indicator, 1)						; индикатор под текстом, т.е. не затеняет его
SendMessage_(ScintillaHandle, #SCI_INDICSETALPHA, #num_indicator, 127)						; Прозрачность
; SendMessage_(ScintillaHandle, #SCI_INDICGETOUTLINEALPHA, #num_indicator, 255) ; Прозрачность каймы
SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE,0, SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)) ; начало и длина
Color(SelectedWord, 0, SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0))

Re: How to highlight a word in the IDE?

Posted: Mon Jul 29, 2024 4:32 pm
by AZJIO
Selects text, but not all occurrences. If it worked stably, it would be possible to add cleaning and some search settings (case sensitivity, whole word only, etc.). Access is now via file as direct search via Scintilla functions is not available.

Code: Select all

EnableExplicit
Global SelectedWord.s, ScintillaText.s, Path.s
Global PbIdeHandle, ScintillaHandle
Global g_ClassTextIDE.s, g_TitleTextIDE.s
;- ● Declare
Declare.s GetScintillaRangeText(cursor, length)
; ---------------------------------------------------------------------------------------------------------------------

	Global classText.s = Space(256)
; найти окно редактора PureBasic, Notepad++, SciTE
	Procedure.l enumChildren0(hwnd.l)
		If hwnd
			GetClassName_(hwnd, @classText, 256)
			If classText = g_ClassTextIDE
				GetWindowText_(hwnd, @classText, 256)
				; если заголовок не указан, или в нём есть имя редактора, то применить
				If Not Asc(g_TitleTextIDE) Or FindString(classText, g_TitleTextIDE)
					PbIdeHandle = hwnd
					ProcedureReturn 0
				EndIf
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 0
	EndProcedure

; найти Scintilla, для всех трёх редакторов одинаково, так как используются только Scintilla
	Procedure.l enumChildren1(hwnd.l)
		If hwnd
			GetClassName_(hwnd, @classText, 256)
			If classText = "Scintilla"
				ScintillaHandle = hwnd
				ProcedureReturn 0
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 0
	EndProcedure

	Procedure GetWord()
		Protected tmp, WordStart, WordEnd
		tmp = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		SendMessage_(ScintillaHandle, #SCI_WORDLEFT, 0, 0)
		WordStart = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		; Debug WordStart
		SendMessage_(ScintillaHandle, #SCI_WORDRIGHT, 0, 0)
		WordEnd = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		; Debug WordEnd
		SendMessage_(ScintillaHandle, #SCI_SETCURRENTPOS, tmp, 0)
		SendMessage_(ScintillaHandle, #SCI_SETANCHOR, tmp, 0)
		SelectedWord = GetScintillaRangeText(WordStart, WordEnd - WordStart)
		; Debug "|" + SelectedWord + "|"
	EndProcedure

Procedure.s GetScintillaRangeText(cursor, length)
	Protected ReturnValue.s
; 	Protected length
	Protected *buffer
	Protected processId
	Protected hProcess
	Protected result

	If length
		*buffer = AllocateMemory(length + 2)
		If *buffer
			SendMessageTimeout_(ScintillaHandle, #SCI_GETRANGEPOINTER, cursor, 0, #SMTO_ABORTIFHUNG, 2000, @result)
			If result
				GetWindowThreadProcessId_(ScintillaHandle, @processId)
				hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, processId)
				If hProcess
					ReadProcessMemory_(hProcess, result, *buffer, length, 0)
					ReturnValue = PeekS(*buffer, -1, #PB_UTF8)
					CloseHandle_(hProcess)
				EndIf
			EndIf
		EndIf
		FreeMemory(*buffer)
	EndIf
	ProcedureReturn ReturnValue
EndProcedure


Procedure Initialization()
	Protected Anchor, Cursor, LenSel, rex1, SelectedWord2.s, CountParam, Title.s, tmp.s, Last, pos
; 	Protected Text.string
	Protected IsWord
; g_ClassTextIDE
; g_TitleTextIDE

	; 	Если переданы параметры, то получить доступ через них.
	CountParam = CountProgramParameters()
	If CountParam > 1
; 		Первые 2 параметра определяют окно с которым работать - класс и заголовок
		g_TitleTextIDE = ProgramParameter(0)
		g_ClassTextIDE = ProgramParameter(1)
		; 		MessageRequester("PathFile$", PathFile$)

		; 		MessageRequester("", SelectedWord + #CRLF$ + Str(CursorLine) + #CRLF$ + PathFile$ + #CRLF$ + NameEditor$)

		EnumChildWindows_(0, @enumChildren0(), 0)
		If CountParam > 3 : MessageRequester("", Str(PbIdeHandle)) : EndIf
		If Not PbIdeHandle : End : EndIf
		EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
		; 		MessageRequester("0", Str(PbIdeHandle) + #CRLF$ + Str(ScintillaHandle))
		If CountParam > 3 : MessageRequester("Scintilla", Str(ScintillaHandle)) : EndIf
		If Not ScintillaHandle : End : EndIf
		
		If CountParam > 2
			SelectedWord = ProgramParameter(2)
		Else
			GetWord()
		EndIf
		If CountParam > 3
; 			MessageRequester("", SelectedWord)
			Path = ProgramParameter(3)
		EndIf

; 		tmp = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
; 		CursorLine = SendMessage_(ScintillaHandle, #SCI_LINEFROMPOSITION, tmp, 0)


		; 		tmp = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)


	Else

		CompilerIf #PB_Compiler_Debugger
			; блок кода только для теста, по нажатию F5
			g_TitleTextIDE = "PureBasic"
			g_ClassTextIDE = "WindowClass_2"
			EnumChildWindows_(0, @enumChildren0(), 0)
			EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
			Path = #PB_Compiler_File
			; конец: блок кода только для теста
		CompilerElse
; 			без пераметров считаем что PureBasic и берём из переменных среды
			PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
			If Not PbIdeHandle : End : EndIf

			ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
			If Not ScintillaHandle : End : EndIf
			SelectedWord = GetEnvironmentVariable("PB_TOOL_Word")
			
			Title = Space(500)
			GetWindowText_(PbIdeHandle, Title, 500)
			If FindString(Title, "\")
				pos = FindString(Title, " - ")
				If pos
					Title = Mid(Title, pos + 3)
					If FileSize(Title) > 0
						Path = Title
					Else
						End
					EndIf
				EndIf
			Else
				pos = FindString(Title, " - ")
				If pos
					Title = Mid(Title, pos + 3)
					tmp = GetEnvironmentVariable("PB_TOOL_FileList")
					If CountString(tmp, Title) = 1
						pos = FindString(tmp, Title)
						If pos
							tmp = Mid(tmp, 1, pos - 1)
							If CountString(tmp, #LF$)
								pos = 0
								Repeat
									Last = pos
									pos = FindString(tmp , #LF$, pos + 1)
								Until Not pos
								tmp = Mid(tmp, Last + 1) + Title
							Else
								tmp + Title
							EndIf
						EndIf
						If FileSize(tmp) > 0
							Path = tmp
; 							MessageRequester("Существует", Path)
						Else
							End
						EndIf
					EndIf
				EndIf
				
			EndIf
		CompilerEndIf

	EndIf
	#File = 0
	If ReadFile(#File, Path)
		ReadStringFormat(#File)
		ScintillaText = ReadString(#File, #PB_UTF8 | #PB_File_IgnoreEOL)
		CloseFile(#File)
	Else
		Debug #PB_Compiler_File
		Debug GetPathPart(ProgramFilename()) + #PB_Compiler_Filename
	EndIf

; так как найдена Scintilla, то пробуем получить выделенный текст
; 	CursorLine = Int(Val(StringField(GetEnvironmentVariable("PB_TOOL_Cursor"), 1, "x")))
; 	MessageRequester("PB_TOOL_Cursor", Str(CursorLine))
	Cursor = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
	Anchor = SendMessage_(ScintillaHandle, #SCI_GETANCHOR, 0, 0)
	If Anchor <> Cursor
		If Anchor < Cursor
			LenSel = Cursor - Anchor
			Cursor = Anchor
		Else
			LenSel = Anchor - Cursor
		EndIf
		SelectedWord2 = GetScintillaRangeText(Cursor, LenSel)
		If FindString(SelectedWord2, #LF$)
			End
		EndIf

		rex1 = CreateRegularExpression(#PB_Any, "\A\w+\z", #PB_RegularExpression_NoCase)
		If Not MatchRegularExpression(rex1, SelectedWord2)
			IsWord = 0
		EndIf
		FreeRegularExpression(rex1)
	EndIf
; 	CursorLine = SendMessage_(ScintillaHandle, #SCI_LINEFROMPOSITION, Cursor, 0) + 1

; 	Здесь различие между выделенным целым словом и частью слова, чтобы часть слова искать не как целое, без \b
	If Asc(SelectedWord2) And SelectedWord2 <> SelectedWord
		SelectedWord = SelectedWord2
	Else
		IsWord = 1
	EndIf


	CompilerIf #PB_Compiler_Debugger
		If Not Asc(SelectedWord) And CountParam = 0
			GetWord()
		EndIf
	CompilerEndIf
EndProcedure

Initialization()
Debug "Scintilla = " + ScintillaHandle
Debug "SelectedWord = " + SelectedWord

;- RegExp подсветка стандартного текста
Procedure Color()
	Protected BytePos, len1, len2, pos
	
	Debug "CountString = " + CountString(ScintillaText, SelectedWord)
; 	If CountString(SelectedWord, " ")
; 		ProcedureReturn
; 	EndIf
	len1 = Len(SelectedWord)
; 	len2 = Len(SelectedWord)
	len2 = StringByteLength(SelectedWord, #PB_UTF8)
	
	
	pos = 1
	Repeat
		pos = FindString(ScintillaText, SelectedWord, pos, #PB_String_NoCase)
		Debug pos
		If pos
			BytePos = StringByteLength(Mid(ScintillaText, 1, pos - 1), #PB_UTF8) ; позиция в байтах
			Debug "= " + BytePos
			SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE, BytePos, len2) ; начало и длина
; 			SendMessage_(ScintillaHandle, #SCI_GOTOPOS, BytePos, 0) ; показывает что точно пробегается по позициям
			pos + len1
		Else
			Break
		EndIf
	ForEver
EndProcedure


#num_indicator = 19
; #num_indicator = 13

Define *Text, nLine, start, length

SendMessage_(ScintillaHandle, #SCI_INDICSETSTYLE, #num_indicator, #INDIC_STRAIGHTBOX) ; первый индикатор со стилем 8 (0-19)
SendMessage_(ScintillaHandle, #SCI_INDICSETFORE, #num_indicator, #Red)				  ; первый индикатор с красным цветом
SendMessage_(ScintillaHandle, #SCI_SETINDICATORCURRENT, #num_indicator, #INDIC_STRAIGHTBOX) ; делает индикатор текущим
SendMessage_(ScintillaHandle, #SCI_INDICSETUNDER, #num_indicator, 1)						; индикатор под текстом, т.е. не затеняет его
SendMessage_(ScintillaHandle, #SCI_INDICSETALPHA, #num_indicator, 127)						; Прозрачность
; SendMessage_(ScintillaHandle, #SCI_INDICGETOUTLINEALPHA, #num_indicator, 255) ; Прозрачность каймы
; SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE,0, SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)) ; начало и длина


;-┌──GUI──┐
If OpenWindow(0, 0, 0, 160, 170, "Метки...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_Tool)
	ButtonGadget(1, 10, 10, 140, 30, "Подсветить")
	ButtonGadget(2, 10, 50, 140, 30, "Очистка")
	StringGadget(3, 10, 90, 140, 30, "")
	SetGadgetText(3, SelectedWord)
	TextGadget(4, 10, 130, 140, 30, "")
	SetGadgetText(4, "Найдено: " + Str(CountString(ScintillaText, SelectedWord)))

;-┌──Loop──┐
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				Select EventGadget()
					Case 1
						SelectedWord = GetGadgetText(3)
						If Asc(SelectedWord)
							Color()
						EndIf
						Break
					Case 2
						SendMessage_(ScintillaHandle, #SCI_INDICATORCLEARRANGE, 0, SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)) 
						Break
				EndSelect
			Case #PB_Event_CloseWindow
				Break
		EndSelect
	ForEver
EndIf

CloseWindow(0)
End

Re: How to highlight a word in the IDE?

Posted: Thu Sep 26, 2024 5:08 pm
by Webarion
AZJIO wrote: Mon Jul 29, 2024 4:32 pm Selects text, but not all occurrences. If it worked stably, it would be possible to add cleaning and some search settings (case sensitivity, whole word only, etc.). Access is now via file as direct search via Scintilla functions is not available.
This may happen because a text editor or IDE is constantly running with Scintilla and may change the current indicator. Before installing and cleaning the indicator, make it current, then everything will work. You will also need a short delay after installing the indicator:

Code: Select all

EnableExplicit

#num_indicator = 19
; #num_indicator = 13

Global SelectedWord.s, ScintillaText.s, Path.s
Global PbIdeHandle, ScintillaHandle
Global g_ClassTextIDE.s, g_TitleTextIDE.s
;- ● Declare
Declare.s GetScintillaRangeText(cursor, length)
; ---------------------------------------------------------------------------------------------------------------------

	Global classText.s = Space(256)
; найти окно редактора PureBasic, Notepad++, SciTE
	Procedure.l enumChildren0(hwnd.l)
		If hwnd
			GetClassName_(hwnd, @classText, 256)
			If classText = g_ClassTextIDE
				GetWindowText_(hwnd, @classText, 256)
				; если заголовок не указан, или в нём есть имя редактора, то применить
				If Not Asc(g_TitleTextIDE) Or FindString(classText, g_TitleTextIDE)
					PbIdeHandle = hwnd
					ProcedureReturn 0
				EndIf
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 0
	EndProcedure

; найти Scintilla, для всех трёх редакторов одинаково, так как используются только Scintilla
	Procedure.l enumChildren1(hwnd.l)
		If hwnd
			GetClassName_(hwnd, @classText, 256)
			If classText = "Scintilla"
				ScintillaHandle = hwnd
				ProcedureReturn 0
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 0
	EndProcedure

	Procedure GetWord()
		Protected tmp, WordStart, WordEnd
		tmp = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		SendMessage_(ScintillaHandle, #SCI_WORDLEFT, 0, 0)
		WordStart = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		; Debug WordStart
		SendMessage_(ScintillaHandle, #SCI_WORDRIGHT, 0, 0)
		WordEnd = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
		; Debug WordEnd
		SendMessage_(ScintillaHandle, #SCI_SETCURRENTPOS, tmp, 0)
		SendMessage_(ScintillaHandle, #SCI_SETANCHOR, tmp, 0)
		SelectedWord = GetScintillaRangeText(WordStart, WordEnd - WordStart)
		; Debug "|" + SelectedWord + "|"
	EndProcedure

Procedure.s GetScintillaRangeText(cursor, length)
	Protected ReturnValue.s
; 	Protected length
	Protected *buffer
	Protected processId
	Protected hProcess
	Protected result

	If length
		*buffer = AllocateMemory(length + 2)
		If *buffer
			SendMessageTimeout_(ScintillaHandle, #SCI_GETRANGEPOINTER, cursor, 0, #SMTO_ABORTIFHUNG, 2000, @result)
			If result
				GetWindowThreadProcessId_(ScintillaHandle, @processId)
				hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, processId)
				If hProcess
					ReadProcessMemory_(hProcess, result, *buffer, length, 0)
					ReturnValue = PeekS(*buffer, -1, #PB_UTF8)
					CloseHandle_(hProcess)
				EndIf
			EndIf
		EndIf
		FreeMemory(*buffer)
	EndIf
	ProcedureReturn ReturnValue
EndProcedure


Procedure Initialization()
	Protected Anchor, Cursor, LenSel, rex1, SelectedWord2.s, CountParam, Title.s, tmp.s, Last, pos
; 	Protected Text.string
	Protected IsWord
; g_ClassTextIDE
; g_TitleTextIDE

	; 	Если переданы параметры, то получить доступ через них.
	CountParam = CountProgramParameters()
	If CountParam > 1
; 		Первые 2 параметра определяют окно с которым работать - класс и заголовок
		g_TitleTextIDE = ProgramParameter(0)
		g_ClassTextIDE = ProgramParameter(1)
		; 		MessageRequester("PathFile$", PathFile$)

		; 		MessageRequester("", SelectedWord + #CRLF$ + Str(CursorLine) + #CRLF$ + PathFile$ + #CRLF$ + NameEditor$)

		EnumChildWindows_(0, @enumChildren0(), 0)
		If CountParam > 3 : MessageRequester("", Str(PbIdeHandle)) : EndIf
		If Not PbIdeHandle : End : EndIf
		EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
		; 		MessageRequester("0", Str(PbIdeHandle) + #CRLF$ + Str(ScintillaHandle))
		If CountParam > 3 : MessageRequester("Scintilla", Str(ScintillaHandle)) : EndIf
		If Not ScintillaHandle : End : EndIf
		
		If CountParam > 2
			SelectedWord = ProgramParameter(2)
		Else
			GetWord()
		EndIf
		If CountParam > 3
; 			MessageRequester("", SelectedWord)
			Path = ProgramParameter(3)
		EndIf

; 		tmp = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
; 		CursorLine = SendMessage_(ScintillaHandle, #SCI_LINEFROMPOSITION, tmp, 0)


		; 		tmp = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)


	Else

		CompilerIf #PB_Compiler_Debugger
			; блок кода только для теста, по нажатию F5
			g_TitleTextIDE = "PureBasic"
			g_ClassTextIDE = "WindowClass_2"
			EnumChildWindows_(0, @enumChildren0(), 0)
			EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
			Path = #PB_Compiler_File
			; конец: блок кода только для теста
		CompilerElse
; 			без пераметров считаем что PureBasic и берём из переменных среды
			PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
			If Not PbIdeHandle : End : EndIf

			ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
			If Not ScintillaHandle : End : EndIf
			SelectedWord = GetEnvironmentVariable("PB_TOOL_Word")
			
			Title = Space(500)
			GetWindowText_(PbIdeHandle, Title, 500)
			If FindString(Title, "\")
				pos = FindString(Title, " - ")
				If pos
					Title = Mid(Title, pos + 3)
					If FileSize(Title) > 0
						Path = Title
					Else
						End
					EndIf
				EndIf
			Else
				pos = FindString(Title, " - ")
				If pos
					Title = Mid(Title, pos + 3)
					tmp = GetEnvironmentVariable("PB_TOOL_FileList")
					If CountString(tmp, Title) = 1
						pos = FindString(tmp, Title)
						If pos
							tmp = Mid(tmp, 1, pos - 1)
							If CountString(tmp, #LF$)
								pos = 0
								Repeat
									Last = pos
									pos = FindString(tmp , #LF$, pos + 1)
								Until Not pos
								tmp = Mid(tmp, Last + 1) + Title
							Else
								tmp + Title
							EndIf
						EndIf
						If FileSize(tmp) > 0
							Path = tmp
; 							MessageRequester("Существует", Path)
						Else
							End
						EndIf
					EndIf
				EndIf
				
			EndIf
		CompilerEndIf

	EndIf
	#File = 0
	If ReadFile(#File, Path)
		ReadStringFormat(#File)
		ScintillaText = ReadString(#File, #PB_UTF8 | #PB_File_IgnoreEOL)
		CloseFile(#File)
	Else
		Debug #PB_Compiler_File
		Debug GetPathPart(ProgramFilename()) + #PB_Compiler_Filename
	EndIf

; так как найдена Scintilla, то пробуем получить выделенный текст
; 	CursorLine = Int(Val(StringField(GetEnvironmentVariable("PB_TOOL_Cursor"), 1, "x")))
; 	MessageRequester("PB_TOOL_Cursor", Str(CursorLine))
	Cursor = SendMessage_(ScintillaHandle, #SCI_GETCURRENTPOS, 0, 0)
	Anchor = SendMessage_(ScintillaHandle, #SCI_GETANCHOR, 0, 0)
	If Anchor <> Cursor
		If Anchor < Cursor
			LenSel = Cursor - Anchor
			Cursor = Anchor
		Else
			LenSel = Anchor - Cursor
		EndIf
		SelectedWord2 = GetScintillaRangeText(Cursor, LenSel)
		If FindString(SelectedWord2, #LF$)
			End
		EndIf

		rex1 = CreateRegularExpression(#PB_Any, "\A\w+\z", #PB_RegularExpression_NoCase)
		If Not MatchRegularExpression(rex1, SelectedWord2)
			IsWord = 0
		EndIf
		FreeRegularExpression(rex1)
	EndIf
; 	CursorLine = SendMessage_(ScintillaHandle, #SCI_LINEFROMPOSITION, Cursor, 0) + 1

; 	Здесь различие между выделенным целым словом и частью слова, чтобы часть слова искать не как целое, без \b
	If Asc(SelectedWord2) And SelectedWord2 <> SelectedWord
		SelectedWord = SelectedWord2
	Else
		IsWord = 1
	EndIf


	CompilerIf #PB_Compiler_Debugger
		If Not Asc(SelectedWord) And CountParam = 0
			GetWord()
		EndIf
	CompilerEndIf
EndProcedure

Initialization()
Debug "Scintilla = " + ScintillaHandle
Debug "SelectedWord = " + SelectedWord

;- RegExp подсветка стандартного текста
Procedure Color()
	Protected BytePos, len1, len2, pos
	
	Debug "CountString = " + CountString(ScintillaText, SelectedWord)
; 	If CountString(SelectedWord, " ")
; 		ProcedureReturn
; 	EndIf
	len1 = Len(SelectedWord)
; 	len2 = Len(SelectedWord)
	len2 = StringByteLength(SelectedWord, #PB_UTF8)
	
	
	pos = 1
	Repeat
		pos = FindString(ScintillaText, SelectedWord, pos, #PB_String_NoCase)
		Debug pos
		If pos
			BytePos = StringByteLength(Mid(ScintillaText, 1, pos - 1), #PB_UTF8) ; позиция в байтах
			Debug "= " + BytePos
			SendMessage_(ScintillaHandle, #SCI_SETINDICATORCURRENT, #num_indicator, 0)
			SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE, BytePos, len2) ; начало и длина
			Delay(10)
; 			SendMessage_(ScintillaHandle, #SCI_GOTOPOS, BytePos, 0) ; показывает что точно пробегается по позициям
			pos + len1
		Else
			Break
		EndIf
	ForEver
EndProcedure




Define *Text, nLine, start, length

SendMessage_(ScintillaHandle, #SCI_INDICSETSTYLE, #num_indicator, #INDIC_STRAIGHTBOX) ; первый индикатор со стилем 8 (0-19)
SendMessage_(ScintillaHandle, #SCI_INDICSETFORE, #num_indicator, #Red)				  ; первый индикатор с красным цветом
SendMessage_(ScintillaHandle, #SCI_SETINDICATORCURRENT, #num_indicator, #INDIC_STRAIGHTBOX) ; делает индикатор текущим
SendMessage_(ScintillaHandle, #SCI_INDICSETUNDER, #num_indicator, 1)						; индикатор под текстом, т.е. не затеняет его
SendMessage_(ScintillaHandle, #SCI_INDICSETALPHA, #num_indicator, 127)						; Прозрачность
; SendMessage_(ScintillaHandle, #SCI_INDICGETOUTLINEALPHA, #num_indicator, 255) ; Прозрачность каймы
; SendMessage_(ScintillaHandle, #SCI_INDICATORFILLRANGE,0, SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)) ; начало и длина


;-┌──GUI──┐
If OpenWindow(0, 0, 0, 160, 170, "Метки...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_Tool)
  StickyWindow(0,#True)
	ButtonGadget(1, 10, 10, 140, 30, "Подсветить")
	ButtonGadget(2, 10, 50, 140, 30, "Очистка")
	StringGadget(3, 10, 90, 140, 30, "")
	SetGadgetText(3, SelectedWord)
	TextGadget(4, 10, 130, 140, 30, "")
	SetGadgetText(4, "Найдено: " + Str(CountString(ScintillaText, SelectedWord)))

;-┌──Loop──┐
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				Select EventGadget()
					Case 1
						SelectedWord = GetGadgetText(3)
						If Asc(SelectedWord)
							Color()
						EndIf
						Break
					Case 2
					  SendMessage_(ScintillaHandle, #SCI_SETINDICATORCURRENT, #num_indicator, 0)
						SendMessage_(ScintillaHandle, #SCI_INDICATORCLEARRANGE, 0, SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)) 
						Break
				EndSelect
			Case #PB_Event_CloseWindow
				Break
		EndSelect
	ForEver
EndIf

CloseWindow(0)
End

Re: How to highlight a word in the IDE?

Posted: Thu Sep 26, 2024 6:02 pm
by Webarion
You can also do the following before installing and cleaning the indicator:

Code: Select all

If SendMessage_(ScintillaHandle, #SCI_GETINDICATORCURRENT, #num_indicator, 0) <> #num_indicator
  SendMessage_(ScintillaHandle, #SCI_SETINDICATORCURRENT, #num_indicator, 0)
EndIf

Re: How to highlight a word in the IDE?

Posted: Thu Oct 03, 2024 9:39 am
by renmsa
Check SelectedWord: Ensure that SelectedWord holds the word you want to highlight by outputting it for debugging. You can use Debug SelectedWord to confirm the correct word is selected.

Verify the Range for Highlighting: When calling the Color procedure, you are sending 0 as the starting position. Ensure that this aligns with the intended starting position of the word to be highlighted. You may want to pass the exact start and end positions calculated by the GetWord() procedurebackrooms game