How to highlight a word in the IDE?
Posted: Sun Jul 28, 2024 1:26 pm
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))