Page 1 of 5

Show all occurrences of a word in the IDE

Posted: Fri Feb 10, 2023 3:41 pm
by Mesa
On this German thread https://www.purebasic.fr/german/viewtopic.php?t=28292, there is a very usefull tool.
We can add this very practical option using a keyboard shortcut.

However, it doesn't show constants so I added a little snippet of code that does this.

Code: Select all

;   Description: Find all references of a variable
;            OS: Windows
; English-Forum: 
;  French-Forum: 
;  German-Forum: http://www.purebasic.fr/german/viewtopic.php?f=8&t=28292
;-----------------------------------------------------------------------------

; MIT License
; 
; Copyright (c) 2015 Kiffi
; 
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
; 
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
; 
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.

; FindAllReferences



CompilerIf #PB_Compiler_OS<>#PB_OS_Windows
	CompilerError "Windows Only!"
CompilerEndIf

EnableExplicit

Enumeration ; Windows
	#frmMain
EndEnumeration
Enumeration ; Gadgets
	#frmMain_References
EndEnumeration
Enumeration ; Menu-/Toolbaritems
	#frmMain_Shortcut_Escape_Event
EndEnumeration

Global PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
If PbIdeHandle = 0 : End : EndIf

Global ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
If ScintillaHandle = 0 : End : EndIf

Procedure.s RemoveLeadingWhitespaceFromString(InString.s)
	
	While Left(InString, 1) = Chr(32) Or Left(InString, 1) = Chr(9)
		InString = LTrim(InString, Chr(32))
		InString = LTrim(InString, Chr(9))
	Wend
	
	ProcedureReturn InString
	
EndProcedure

Procedure.s GetScintillaText()
	
	Protected ReturnValue.s
	
	Protected length
	Protected buffer
	Protected processId
	Protected hProcess
	Protected result
	
	length = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)
	If length
		length + 2
		buffer = AllocateMemory(length)
		If buffer   
			SendMessageTimeout_(ScintillaHandle, #SCI_GETCHARACTERPOINTER, 0, 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)
				EndIf
			EndIf
		EndIf
		FreeMemory(buffer)
	EndIf
	
	ProcedureReturn ReturnValue
	
EndProcedure

Procedure frmMain_SizeWindow_Event()
	ResizeGadget(#frmMain_References, #PB_Ignore, #PB_Ignore, WindowWidth(#frmMain) - 20, WindowHeight(#frmMain) - 20)
EndProcedure

Procedure frmMain_References_Event()
	
	Protected SelectedLine
	
	SelectedLine = Val(GetGadgetItemText(#frmMain_References, GetGadgetState(#frmMain_References), 0))
	
	If SelectedLine > 0
		SendMessage_(ScintillaHandle, #SCI_GOTOLINE, SelectedLine - 1, 0)
		SendMessage_(ScintillaHandle, #SCI_ENSUREVISIBLE, SelectedLine - 1, 0)
		SetForegroundWindow_(PbIdeHandle)
		SetActiveWindow_(PbIdeHandle)
	EndIf
	
EndProcedure

Define SelectedWord.s = GetEnvironmentVariable("PB_TOOL_Word")
If SelectedWord = "" : End : EndIf

Define ScintillaText.s = GetScintillaText()
If ScintillaText = "" : End : EndIf

Define Line.s
Define CountLines, LineCounter
Define CountTokens, TokenCounter
Define WWE
Define RegexLines, PbRegexTokens

Structure sFoundReference
	LineNo.i
	Reference.s
	
EndStructure

NewList FoundReference.sFoundReference()

Dim Tokens.s(0)


;http://www.purebasic.fr/english/viewtopic.php?f=12&t=37823
RegexLines = CreateRegularExpression(#PB_Any , ".*\r\n")
PbRegexTokens = CreateRegularExpression(#PB_Any, #DOUBLEQUOTE$ + "[^" + #DOUBLEQUOTE$ + "]*" + #DOUBLEQUOTE$ + "|[\*]?[a-zA-Z_]+[\w]*[\x24]?|#[a-zA-Z_]+[\w]*[\x24]?|[\[\]\(\)\{\}]|[-+]?[0-9]*\.?[0-9]+|;.*|\.|\+|-|[&@!\\\/\*,\|]|::|:|\|<>|>>|<<|=>{1}|>={1}|<={1}|=<{1}|={1}|<{1}|>{1}|\x24+[0-9a-fA-F]+|\%[0-1]*|%|'")

CountLines = CountString(ScintillaText, #CRLF$)

Dim Lines.s(0)

CountLines = ExtractRegularExpression(RegexLines, ScintillaText, Lines())

SelectedWord = LCase(SelectedWord)

For LineCounter = 0 To CountLines - 1
	
	Line = Lines(LineCounter)   
	
	CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())
	
	For TokenCounter = 0 To CountTokens - 1   
		If SelectedWord = LCase(Tokens(TokenCounter))
			AddElement(FoundReference())
			FoundReference()\LineNo = LineCounter + 1
			Line = Trim(Line)
			Line = Mid(Line, 1, Len(Line)-2)
			FoundReference()\Reference = Line
		EndIf
		
	Next
	
Next

If ListSize(FoundReference()) = 0
	
	SelectedWord = "#" + SelectedWord
	
	For LineCounter = 0 To CountLines - 1
		
		Line = Lines(LineCounter)   
		
		CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())
		
		For TokenCounter = 0 To CountTokens - 1   
			If SelectedWord = LCase(Tokens(TokenCounter))
				AddElement(FoundReference())
				FoundReference()\LineNo = LineCounter + 1
				Line = Trim(Line)
				Line = Mid(Line, 1, Len(Line)-2)
				FoundReference()\Reference = Line
			EndIf
			
		Next
		
	Next	
	
	If ListSize(FoundReference()) = 0 : End : EndIf
EndIf

OpenWindow(#frmMain,
           #PB_Ignore,
           #PB_Ignore,
           600,
           300,
           "Display all: '" + SelectedWord + "'",
           #PB_Window_SystemMenu |
           #PB_Window_SizeGadget |
           #PB_Window_ScreenCentered)

StickyWindow(#frmMain, #True)

ListIconGadget(#frmMain_References,
               10,
               10,
               WindowWidth(#frmMain) - 20,
               WindowHeight(#frmMain) - 20,
               "Line",
               50,
               #PB_ListIcon_FullRowSelect |   
               #PB_ListIcon_GridLines |
               #PB_ListIcon_AlwaysShowSelection)

AddGadgetColumn(#frmMain_References, 1, "Ref", 400)


ForEach FoundReference()
	AddGadgetItem(#frmMain_References, -1, Str(FoundReference()\LineNo) + #LF$ + FoundReference()\Reference)   
Next

Define i

SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 0, #LVSCW_AUTOSIZE_USEHEADER)
SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 1, #LVSCW_AUTOSIZE)
SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 2, #LVSCW_AUTOSIZE)

AddKeyboardShortcut(#frmMain, #PB_Shortcut_Escape, #frmMain_Shortcut_Escape_Event)
BindEvent(#PB_Event_SizeWindow, @frmMain_SizeWindow_Event(), #frmMain)
BindGadgetEvent(#frmMain_References, @frmMain_References_Event())
SetActiveGadget(#frmMain_References)


Repeat
	
	WWE = WaitWindowEvent()
	
	If (WWE = #PB_Event_Menu And EventMenu() = #frmMain_Shortcut_Escape_Event) Or (WWE = #PB_Event_CloseWindow)
		Break
	EndIf
	
ForEver
My final version with the use of a scintilla gadget and your own PB settings
[Edit] Fix title window.
[Edit Sept 2024] New regex procedure public/private and more, tools like copy, declaration making...
Image

Code: Select all

EnableExplicit

;=============================================================
; ----------------------------------------------------------------------------
; File : FindAllReferences[Win].pb
; ----------------------------------------------------------------------------
;
;   Description: Find all references of a variable
;            OS: Windows
;  English-Forum: https://www.purebasic.fr/english/viewtopic.php?t=80739
;  French-Forum : https://www.purebasic.fr/french/viewtopic.php?p=214865
;  German-Forum : http://www.purebasic.fr/german/viewtopic.php?f=8&t=28292
; ----------------------------------------------------------------------------

; MIT License
;
; Copyright (c) 2015 Kiffi
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
;
; ----------------------------------------------------------------------------
; Change Log :
;   2023-02-12 : New Additions from Mesa, AZJIO, Axolotl, Dadlick, ChrisR, Allen
;		2023-03-08 : New scintilla version by Mesa
;   2024-09-04 : New regex procedure public/private and others, tools like copy, declaration making...
;
; English-Forum: https://www.purebasic.fr/english/viewtopic.php?t=80739
;
; History
;   - Mesa added search for constants and renewed interest in the tool
;   - AZJIO embedded highlight using ColorListIconGadget.pb by srod
;   - Axolotl qualitatively rewrote the functionality, making many changes
;   - Axolotl added the ability to test without compiling
;   - AZJIO added regular expressions
;   - ChrisR added a black theme
;   - Dadlick started his own tool fork
;   - AZJIO added a jump test to a string without compiling
;   - AZJIO added a black theme for Header and button
;   - Mesa created a scintilla version
;
; ----------------------------------------------------------------------------

; FindAllReferences

CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
  CompilerError "Windows Only!"
CompilerEndIf

EnableExplicit

;- Enumeration

Enumeration Windows
  #Mainform
EndEnumeration

Enumeration Gadgets
  #cmbRex
  #btnRex
  #btnTools
  #Scintilla
EndEnumeration

Enumeration  Menus
  #Mainform_Shortcut_Escape_Event
  #Shortcut_Ctrl_Shift_C
  #Shortcut_Enter
  #CopyRef
  #CopyProcRef
  #CopyNProcRef
  #Copy2Declaration
EndEnumeration

Enumeration Scintilla_Syntax
  #Scintilla_Text
  #Scintilla_Keyword
  #Scintilla_Comment
  #Scintilla_Constant
  #Scintilla_String
  #Scintilla_Function
  #Scintilla_Asm
  #Scintilla_Operator
  #Scintilla_Structure
  #Scintilla_Number
  #Scintilla_Pointer
  #Scintilla_Separator
  #Scintilla_Label
  #Scintilla_Module
  
  #Scintilla_MyLexer
EndEnumeration

Enumeration File
  #Scintilla_Highlight_DLL
EndEnumeration


;- Structure

Structure sFoundReference
  LineNo.i
  Reference.s
  Selregexp.s
EndStructure

Structure xywhm
  ;ini file
  x.i
  y.i
  w.i
  h.i
  m.i
EndStructure


;- Global
Global ini$ = LSet(ProgramFilename(), Len(ProgramFilename()) - 3) + "ini"
Global centered
Global xywh.xywhm
Global xywh2.xywhm
Global xywh\w = 600
Global xywh\h = 300
Global CursorLine
Global flgRead
Global YouAreHere.s

Global PbIdeHandle, ScintillaHandle

Global SelectedWord.s, PB_ScintillaText.s
Global CountSelectedWords
Global NewList FoundReference.sFoundReference()
Global Dim Lines.s(0)

Global BackColor = $B4DDE8
Global ForeColor = $151515
Global BackColorHeader = $C4CDC8
; Global ForeColorHeader = $151515
Global BorderColor = $888888
Global HightLightBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
Global BackColorBrush = CreateSolidBrush_(BackColor)
Global BackColorBrushHeader = CreateSolidBrush_(BackColorHeader)

; ---------------------------------------------------------------------------------------------------------------------

; ---== Procedures ==--------------------------------------------------------------------------------------------------

;- Procedure
; AZJIO
Procedure.s LTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
  
  Protected *memChar, *c.Character, *jc.Character
  
  If Not Asc(String$)
    ProcedureReturn ""
  EndIf
  
  *c.Character = @String$
  *memChar = @TrimChar$
  
  While *c\c
    *jc.Character = *memChar
    
    While *jc\c
      If *c\c = *jc\c
        *c\c = 0
        Break
      EndIf
      *jc + SizeOf(Character)
    Wend
    
    If *c\c
      String$ = PeekS(*c)
      Break
    EndIf
    *c + SizeOf(Character)
  Wend
  
  ProcedureReturn String$
  
EndProcedure

Procedure.s RemoveLeadingWhitespaceFromString(InString.s)
  
  While Left(InString, 1) = Chr(32) Or Left(InString, 1) = Chr(9)
    InString = LTrim(InString, Chr(32))
    InString = LTrim(InString, Chr(9))
  Wend
  
  ProcedureReturn InString
  
EndProcedure


Procedure.s Get_PB_ScintillaText()
  Protected ReturnValue.s
  Protected length
  Protected buffer
  Protected processId
  Protected hProcess
  Protected result
  
  length = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)
  If length
    length + 2
    buffer = AllocateMemory(length)
    If buffer
      SendMessageTimeout_(ScintillaHandle, #SCI_GETCHARACTERPOINTER, 0, 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)  ; <-- Axolotl, added acc. to MSDN
        EndIf
      EndIf
    EndIf
    FreeMemory(buffer)
  EndIf
  ProcedureReturn ReturnValue
EndProcedure

; ---------------------------------------------------------------------------------------------------------------------

; For test only
Global classText.s = Space(256)
; Finding a PureBasic Window
Procedure.l EnumChildren0(hwnd.l)
  If hwnd
    GetClassName_(hwnd, @classText, 256)
    If classText = "WindowClass_2"
      GetWindowText_(hwnd, @classText, 256)
      If Left(classText, 9) = "PureBasic"
        PbIdeHandle = hwnd
        ProcedureReturn 0
      EndIf
    EndIf
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure

; Finding the PB 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 Initialization()
  
  PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
  CompilerIf Not #PB_Compiler_Debugger
    If PbIdeHandle = 0 : End : EndIf
  CompilerEndIf
  
  ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
  CompilerIf Not #PB_Compiler_Debugger
    If ScintillaHandle = 0 : End : EndIf
  CompilerEndIf
  
  
  ; For test only
  CompilerIf #PB_Compiler_Debugger
    EnumChildWindows_(0, @enumChildren0(), 0)
    EnumChildWindows_(PbIdeHandle, @enumChildren1(), 0)
  CompilerEndIf
  ; End: For test only
  
  
  SelectedWord.s = GetEnvironmentVariable("PB_TOOL_Word")
  CompilerIf Not #PB_Compiler_Debugger
    If SelectedWord = "" : End : EndIf
  CompilerEndIf
  
  PB_ScintillaText.s = Get_PB_ScintillaText()
  CompilerIf Not #PB_Compiler_Debugger
    If PB_ScintillaText = "" : End : EndIf
  CompilerEndIf
  
  CursorLine = Int(Val(StringField(GetEnvironmentVariable("PB_TOOL_Cursor"), 1, "x")))
  
  
  ; For test only
  CompilerIf #PB_Compiler_Debugger
    
    If SelectedWord = ""
      ;     SelectedWord = "Line"    ; try one of these
      ;     SelectedWord = "#Line"   ; -"-  #Line could be in a comment also
      SelectedWord = "PB_ScintillaText"   ; -"-
    EndIf
    
    If PB_ScintillaText = ""
      #File = 0
      If ReadFile(#File, #PB_Compiler_File)
        PB_ScintillaText = ReadString(#File, #PB_UTF8 | #PB_File_IgnoreEOL)
        CloseFile(#File)
      EndIf
      ; 			RunProgram("explorer.exe", "/Select," + #PB_Compiler_File, "")
      
      ; 			PB_ScintillaText = "" + #CRLF$ +
      ; 			                "#Line = #LF ;  #Line could be in a comment also " + #CRLF$ +
      ; 			                "Procedure Test(*Line)  ; pointer *Line " + #CRLF$ +
      ; 			                "" + #CRLF$ +
      ; 			                "If SelectedWord = LCase(Tokens(TokenCounter))" + #CRLF$ +
      ; 			                "	 AddElement(FoundReference())" + #CRLF$ +
      ; 			                "	 FoundReference()\LineNo = LineCounter + 1" + #CRLF$ +
      ; 			                "	 Line = Trim(Line)" + #CRLF$ +
      ; 			                "	 Line = Mid(Line, 1, Len(Line)-2)" + #CRLF$ +
      ; 			                "	 FoundReference()\Reference = Line" + #CRLF$ +
      ; 			                "EndIf" + #CRLF$ +
      ; 			                "" ; End of Text
    EndIf
  CompilerEndIf
  ; End: For test only
  
  ProcedureReturn 0  ; default (ZERO is returned by default, even if there is no ProcedureReturn)
EndProcedure

; ---------------------------------------------------------------------------------------------------------------------



;highlighting via indicator 
Procedure ScintillaIndicColor(*regex, regexLength, n, p=6)
  
  Protected txtLen, StartPos, EndPos, firstMatchPos
  
  ; Sets search mode (REGEX + POSIX braces)
  ScintillaSendMessage(#Scintilla, #SCI_SETSEARCHFLAGS, #SCFIND_REGEXP | #SCFIND_POSIX)
  
  ; Sets target search range
  txtLen = ScintillaSendMessage(#Scintilla, #SCI_GETTEXTLENGTH) ; gets the text length
  ScintillaSendMessage(#Scintilla, #SCI_INDICSETSTYLE, n, p)    ; #INDIC_TEXTFORE = 17 creates an indicator with number 7 (occupied by default 0, 1, 2)
  ScintillaSendMessage(#Scintilla, #SCI_INDICSETFORE, n, $3A3AE7) ; assign colour of indicator number 7 - green
  
  EndPos = 0
  Repeat
    ScintillaSendMessage(#Scintilla, #SCI_SETTARGETSTART, EndPos) ; from the beginning (set the search area) using the position of the previous search end
    ScintillaSendMessage(#Scintilla, #SCI_SETTARGETEND, txtLen)   ; to the end by the text length
    firstMatchPos=ScintillaSendMessage(#Scintilla, #SCI_SEARCHINTARGET, regexLength, *regex) ; returns the position of the first found. The parameters are length and pointer
    If firstMatchPos>-1                                                                      ; if greater than -1, that is found
      StartPos=ScintillaSendMessage(#Scintilla, #SCI_GETTARGETSTART)                         ; it gets position of the first found
      EndPos=ScintillaSendMessage(#Scintilla, #SCI_GETTARGETEND)                             ; gets position of the end of found
      ScintillaSendMessage(#Scintilla, #SCI_SETINDICATORCURRENT, n)                          ; makes the indicator number 7 current
      ScintillaSendMessage(#Scintilla, #SCI_INDICATORFILLRANGE, StartPos, EndPos - StartPos) ; it selects text using the current indicator
    Else
      Break
    EndIf
  ForEver
EndProcedure

;highlighting via style
Procedure ScintillaIndicColor2(*regex, regexLength, n=0)
  Protected txtLen, StartPos, EndPos, firstMatchPos
  
  ; Sets search mode (REGEX + POSIX curly brackets)
  ScintillaSendMessage(#Scintilla, #SCI_SETSEARCHFLAGS, #SCFIND_REGEXP | #SCFIND_POSIX)
  
  ; Sets target search range
  txtLen = ScintillaSendMessage(#Scintilla, #SCI_GETTEXTLENGTH) ; gets the text length
  
  EndPos = 0
  Repeat
    ScintillaSendMessage(#Scintilla, #SCI_SETTARGETSTART, EndPos) ; from the beginning (set the search area) using the position of the previous search end
    ScintillaSendMessage(#Scintilla, #SCI_SETTARGETEND, txtLen)   ; to the end by the text length
    firstMatchPos=ScintillaSendMessage(#Scintilla, #SCI_SEARCHINTARGET, regexLength, *regex) ; returns the position of the first found. The parameters are length and pointer
    If firstMatchPos>-1                                                                      ; if greater than -1, that is found
      StartPos=ScintillaSendMessage(#Scintilla, #SCI_GETTARGETSTART)                         ; it gets position of the first found
      EndPos=ScintillaSendMessage(#Scintilla, #SCI_GETTARGETEND)                             ; gets position of the end of found
      ScintillaSendMessage(#Scintilla, #SCI_STARTSTYLING, StartPos, 0)                       ; the start position (from the 50th)
      ScintillaSendMessage(#Scintilla, #SCI_SETSTYLING, EndPos - StartPos, #Scintilla_MyLexer)				 ; width and style number
    Else
      Break
    EndIf
  ForEver
EndProcedure

Procedure.s  GetScintillaCurLineText(ScintillaID, NextGadgetID=-1)
  Protected numUtf8Bytes, bufferPtr,  caretPos
  
  Protected *utf8Buffer
  
  numUtf8Bytes = ScintillaSendMessage(ScintillaID,#SCI_GETCURLINE, 0, 0);includes the null
  
  If numUtf8Bytes
    bufferPtr = AllocateMemory(numUtf8Bytes)
    If bufferPtr
      
      *utf8Buffer = bufferPtr
      caretPos = ScintillaSendMessage(ScintillaID, #SCI_GETCURLINE, numUtf8Bytes, *utf8Buffer)
    EndIf
  EndIf
  
  ;Trick to get the scintilla gadget clickable again
  SetActiveGadget(NextGadgetID)
  
  ProcedureReturn PeekS(*utf8Buffer,numUtf8Bytes,#PB_UTF8)
  
EndProcedure

;Dadlick
Procedure.s FindProcedureName(CursorLine)
  
  Protected LineCounter,  Line.s
  
  For LineCounter = CursorLine - 1 To 1 Step - 1   
    Line = RemoveLeadingWhitespaceFromString(StringField(PB_ScintillaText, LineCounter, #CRLF$))
    
    If Left(LCase(Line), Len("endprocedure")) = "endprocedure"
      Break
    EndIf
    
    If Left(LCase(Line), Len("endmacro")) = "endmacro"
      Break
    EndIf
    
    If Left(LCase(Line), Len("procedure")) = "procedure"
      If Left(LCase(Line), Len("procedurereturn")) <> "procedurereturn"
        ProcedureReturn    Line
        Break
      EndIf
    EndIf 
    
    If Left(LCase(Line), Len("macro")) = "macro"
      If Left(LCase(Line), Len("endmacro")) <> "endmacro"
        ProcedureReturn    Line
        Break
      EndIf
    EndIf 
    
  Next LineCounter
  
  ProcedureReturn ""
  
EndProcedure
; ChrisR
Procedure CopyClipboard(option=#CopyRef)
  
  Protected tmp$,text$,Title$
  
  PushListPosition(FoundReference())
  ForEach FoundReference()
    ; 	  Debug FindProcedureName(FoundReference()\LineNo)
    ; 	  Debug FoundReference()\Reference
    If tmp$ : tmp$ + #CRLF$ : EndIf
    If Right(FoundReference()\Reference, 2) = #CRLF$
      Select option
        Case #CopyRef
          tmp$ + " " + Left(FoundReference()\Reference, Len(FoundReference()\Reference) - 2)
          
        Case #CopyProcRef
          tmp$ + " " +   FindProcedureName(FoundReference()\LineNo)+ " " +  Left(FoundReference()\Reference, Len(FoundReference()\Reference) - 2)
          
        Case #CopyNProcRef
          tmp$ + " " +   FoundReference()\LineNo+ " " + FindProcedureName(FoundReference()\LineNo)+ " " +  Left(FoundReference()\Reference, Len(FoundReference()\Reference) - 2)
          
        Case #Copy2Declaration
          tmp$ + " " + Left(FoundReference()\Reference, Len(FoundReference()\Reference) - 2)
          tmp$=ReplaceString(tmp$,"Procedure","Declare")
          
      EndSelect
    Else
      Select option
        Case #CopyRef
          tmp$ + " " +  FoundReference()\Reference
          
        Case #CopyProcRef
          tmp$ + " " +   FindProcedureName(FoundReference()\LineNo)+ " " +  FoundReference()\Reference
          
        Case #CopyNProcRef
          tmp$ + " " +   FoundReference()\LineNo+ " " + FindProcedureName(FoundReference()\LineNo)+ " " +  FoundReference()\Reference
          
        Case #Copy2Declaration
          tmp$ + " " +  FoundReference()\Reference
          tmp$=ReplaceString(tmp$,"Procedure","Decle")  
          
      EndSelect
      ; 		       tmp$ + FoundReference()\Reference
      
    EndIf
  Next
  PopListPosition(FoundReference())
  If tmp$
    text$=ReplaceString(tmp$,#CRLF$,#LF$)
    
    SetClipboardText(text$)
    Title$ = GetWindowTitle(#Mainform)
    SetWindowTitle(#Mainform, " >>> (References copied to the clipboard) <<<")
    Delay(500)
    SetWindowTitle(#Mainform, Title$)
  EndIf
EndProcedure

; AZJIO
Procedure GoRegExp()
  ; LINK : https://www.purebasic.fr/english/viewtopic.php?p=595832#p595832
  Protected rex, LSize, Pos = 0, i, tmp$, regex$
  Protected Dim Tokens.s(0)
  Protected *Texte
  
  ScintillaSendMessage(#Scintilla, #SCI_CLEARALL)
  ClearList(FoundReference())
  
  tmp$ = GetGadgetText(#cmbRex)
  regex$ = tmp$
  If Not Asc(tmp$)
    ProcedureReturn
  EndIf
  
  rex = CreateRegularExpression(#PB_Any, tmp$)
  
  If rex
    If ExamineRegularExpression(rex, PB_ScintillaText)
      While NextRegularExpressionMatch(rex)
        If Not FindString(RegularExpressionMatchString(rex), #LF$)
          AddElement(FoundReference())
          FoundReference()\Selregexp = RegularExpressionMatchString(rex)
          FoundReference()\LineNo = RegularExpressionMatchPosition(rex)
        EndIf
      Wend
    EndIf
  Else
    MessageRequester("Regular expression error", RegularExpressionError())
    ProcedureReturn
  EndIf
  
  LSize = ListSize(FoundReference())
  If LSize > 0
    ; 		If LSize > 5000 And MessageRequester("Continue?", "Found" + Str(LSize) + " rows, Continue?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
    ; 			ProcedureReturn
    ; 		EndIf
    
    Pos = 0
    i = 0
    ForEach FoundReference()
      While Pos < FoundReference()\LineNo
        Pos = FindString(PB_ScintillaText, #LF$, Pos + 1)
        If Pos
          i + 1
        Else
          Break
        EndIf
      Wend
      If i < 1 Or i > ArraySize(Lines())
        Continue
      EndIf
      
      FoundReference()\LineNo = i
      FoundReference()\Reference = Lines(i - 1)
      FoundReference()\Reference = LTrimChar(FoundReference()\Reference, " " + #TAB$)
      
      ; >> first attempt to mark the selected word in the string
      Protected  Texte$=Str(FoundReference()\LineNo) + #TAB$ + "["+FindProcedureName(FoundReference()\LineNo)+"]> " + FoundReference()\Reference
      *Texte=UTF8(Texte$)
      ScintillaSendMessage(#Scintilla, #SCI_APPENDTEXT, Len(Texte$), *Texte) 
    Next
    FreeMemory(*Texte)
    
    
    ForEach FoundReference()
      tmp$=FoundReference()\Selregexp
      If Right(tmp$, 1)="$"
        tmp$=Left(tmp$, Len(tmp$)-1)+"+\$"
      EndIf
      ;The integrated regex in the scintilla gadget need some escapments
      tmp$ = ReplaceString(tmp$, "*", "\*")
      tmp$ = ReplaceString(tmp$, "(", "\(")
      tmp$ = ReplaceString(tmp$, ")", "\)")
      tmp$ = ReplaceString(tmp$, "\", "\\")
      tmp$ = ReplaceString(tmp$, "\\", "\")
      ; ScintillaIndicColor2(UTF8(tmp$), Len(tmp$))
      ScintillaIndicColor(UTF8(tmp$), Len(tmp$),7,7)	
    Next
    
    SelectedWord = StringField(regex$, 1, ")")
    SelectedWord = Right(SelectedWord,Len(SelectedWord)-3)
    SelectedWord=Trim(SelectedWord)
    
    SetWindowTitle(#Mainform,"'" + SelectedWord + "'> "+ CountSelectedWords +" times in " + Str(ListSize(FoundReference())) + " lines" + YouAreHere)
    
  EndIf
  
EndProcedure

Procedure LookForWordUnderCursor()
  ; LINK : http://www.purebasic.fr/english/viewtopic.php?f=12&t=37823
  Protected RegexLines, PbRegexTokens
  Protected CountLines, LineCounter, CountTokens, TokenCounter
  Protected Line.s, selWord.s, stx.s
  Protected Dim Tokens.s(0)
  
  RegexLines = CreateRegularExpression(#PB_Any , ".*\r\n")
  PbRegexTokens = CreateRegularExpression(#PB_Any, #DOUBLEQUOTE$ + "[^" + #DOUBLEQUOTE$ + "]*" + #DOUBLEQUOTE$ + "|[\*]?[a-zA-Z_]+[\w]*[\x24]?|#[a-zA-Z_]+[\w]*[\x24]?|[\[\]\(\)\{\}]|[-+]?[0-9]*\.?[0-9]+|;.*|\.|\+|-|[&@!\\\/\*,\|]|::|:|\|<>|>>|<<|=>{1}|>={1}|<={1}|=<{1}|={1}|<{1}|>{1}|\x24+[0-9a-fA-F]+|\%[0-1]*|%|'")
  
  CountLines = CountString(PB_ScintillaText, #CRLF$)
  
  CountLines = ExtractRegularExpression(RegexLines, PB_ScintillaText, Lines())
  
  selWord = LCase(SelectedWord)  ; keep the original writing
  CountSelectedWords = 0         ; init for new search
  
  For LineCounter = 0 To CountLines - 1
    Line = Lines(LineCounter)
    
    ;Debug "tokenize Line '" + Line + "'"
    
    CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens()) ; tokenize the line
    
    For TokenCounter = 0 To CountTokens - 1
      ;Debug "  check Token '" + Tokens(TokenCounter) + "'"
      
      If selWord = LCase(Tokens(TokenCounter))
        AddElement(FoundReference())
        FoundReference()\LineNo = LineCounter + 1
        
        Line = Trim(Line)
        Line = Mid(Line, 1, Len(Line) - 2)  ; remove the #CRLF$
        
        CountSelectedWords + CountString(LCase(Line), selWord)   ; <-- count SelectedWord in the codeline
        
        FoundReference()\Reference = Line
        Break  ; only one line (evenn if there are more than one SelectedWord )
      EndIf
    Next TokenCounter
  Next LineCounter
  
  ; because of #Constant or *Pointer
  If ListSize(FoundReference()) = 0
    For LineCounter = 0 To CountLines - 1
      Line = Lines(LineCounter)
      CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())
      For TokenCounter = 0 To CountTokens - 1
        stx = LCase(Tokens(TokenCounter))
        If stx = "#" + selWord Or stx = "*" + selWord
          AddElement(FoundReference())
          FoundReference()\LineNo = LineCounter + 1
          
          Line = Trim(Line)
          Line = Mid(Line, 1, Len(Line) - 2)
          
          CountSelectedWords + CountString(LCase(Line), stx)  ; <-- count SelectedWord in the codeline
          
          FoundReference()\Reference = Line
          Break
        EndIf
      Next
    Next
    
    CompilerIf Not #PB_Compiler_Debugger
      If ListSize(FoundReference()) = 0 : End : EndIf
    CompilerEndIf
  EndIf
  
EndProcedure

Procedure  GetNumberLine(String$,TrimChar$ = #TAB$)
  
  Protected *c.Character, *jc.Character,i
  
  If Not Asc(String$)
    ProcedureReturn 0
  EndIf
  
  *c.Character = @String$
  
  While *c\c
    *jc.Character = @TrimChar$
    
    While *jc\c
      i+1
      If *c\c = *jc\c
        Break 2
      EndIf
      *jc + SizeOf(Character)
    Wend
    
    *c + SizeOf(Character)
  Wend
  
  If i
    String$=Left(String$,i-1)
    ProcedureReturn Val(String$)
  Else
    ProcedureReturn 0
  EndIf
  
EndProcedure

Procedure JumpToLine(SelectedLine)
  
  Protected Count
  
  SendMessage_(ScintillaHandle, #SCI_GOTOLINE, SelectedLine - 1, 0)
  Count = SendMessage_(ScintillaHandle, #SCI_LINESONSCREEN, 0, 0) / 2
  SendMessage_(ScintillaHandle, #SCI_SETFIRSTVISIBLELINE, SelectedLine - Count - 1, 0)
  SetForegroundWindow_(PbIdeHandle)
  SetActiveWindow_(PbIdeHandle)
  
EndProcedure


; ---------------------------------------------------------------------------------------------------------------------

;Only to have a combobox nicer
Procedure Callback_Win(hwnd, msg, wParam, lParam)
  Protected Result,  *DrawItem.DRAWITEMSTRUCT, Buffer.s
  Protected  text$
  Protected nNotifyCode
  
  Result = #PB_ProcessPureBasicEvents
  
  Select msg
    Case #WM_COMMAND
      If lParam = GadgetID(#cmbRex)
        nNotifyCode = wParam >> 16 ; HiWord
        If nNotifyCode = #CBN_SELENDCANCEL
          flgRead = 0
        EndIf
        If nNotifyCode = #CBN_DROPDOWN
          flgRead = 1
        EndIf
      EndIf
      
    Case #WM_NCDESTROY
      DeleteObject_(HightLightBrush)
      DeleteObject_(BackColorBrush)
      DeleteObject_(BackColorBrushHeader)
      
      
    Case #WM_CTLCOLOREDIT
      Buffer = Space(64)
      If GetClassName_(GetParent_(lParam), @Buffer, 64)
        If Buffer = "ComboBox"
          SetTextColor_(wParam, #Black)
          SetBkMode_(wParam, #TRANSPARENT)
          ProcedureReturn BackColorBrush
        EndIf
      EndIf
      
    Case #WM_DRAWITEM
      *DrawItem.DRAWITEMSTRUCT = lParam
      If *DrawItem\CtlType = #ODT_COMBOBOX
        If IsGadget(wParam)
          If *DrawItem\itemID <> -1
            If *DrawItem\itemstate & #ODS_SELECTED
              FillRect_(*DrawItem\hDC, *DrawItem\rcitem, HightLightBrush)
            Else
              FillRect_(*DrawItem\hDC, *DrawItem\rcitem, BackColorBrush)
            EndIf
            SetBkMode_(*DrawItem\hDC, #TRANSPARENT)
            SetTextColor_(*DrawItem\hDC, ForeColor)
            Text$ = GetGadgetItemText(*DrawItem\CtlID, *DrawItem\itemID)
            *DrawItem\rcItem\left + DesktopScaledX(4)
            DrawText_(*DrawItem\hDC, Text$, Len(Text$), *DrawItem\rcItem, #DT_LEFT | #DT_SINGLELINE | #DT_VCENTER)
          EndIf
        EndIf
      EndIf
  EndSelect
  ProcedureReturn Result
EndProcedure


; ---------------------------------------------------------------------------------------------------------------------
;Not used    ChrisR
Procedure SetWindowTheme()
  Protected Theme.s, cmbRexID, ChildGadget, Buffer.s
  If OSVersion() >= #PB_OS_Windows_10
    Theme = "DarkMode_Explorer"
  Else
    Theme = "Explorer"
  EndIf
  
  SetWindowTheme_(GadgetID(#Scintilla), @Theme, 0)
  
  cmbRexID = GadgetID(#cmbRex)
  Buffer = Space(64)
  If GetClassName_(cmbRexID, @Buffer, 64)
    If Buffer = "ComboBox"
      If OSVersion() >= #PB_OS_Windows_10 And Theme = "DarkMode_Explorer"
        SetWindowTheme_(cmbRexID, "DarkMode_CFD", "Combobox")
      Else
        SetWindowTheme_(cmbRexID, @Theme, 0)
      EndIf
    EndIf
  EndIf
  ChildGadget = GetWindow_(cmbRexID, #GW_CHILD)
  If ChildGadget
    Buffer = Space(64)
    If GetClassName_(ChildGadget, @Buffer, 64)
      If Buffer = "ComboBox"
        If OSVersion() >= #PB_OS_Windows_10 And Theme = "DarkMode_Explorer"
          SetWindowTheme_(ChildGadget, "DarkMode_CFD", "Combobox")
        Else
          SetWindowTheme_(ChildGadget, @Theme, 0)
        EndIf
      EndIf
    EndIf
  EndIf
EndProcedure

;For test only
Macro TEST
  Debug "ok"
EndMacro
Macro TEST2(ok)
  Debug  ok
EndMacro

; ---------------------------------------------------------------------------------------------------------------------

;-.............Scintilla...........
;=============================================================

;Global
Global SciPositionStart, *Buffer

;-Declare
Declare CallbackHighlight(*Position, Length, IdColor)
Declare ScintillaCallBack(Gadget.i, *scinotify.SCNotification)


;- Callback Procedures
Procedure CallbackHighlight(*Position, Length, IdColor)
  
  Shared SciPositionStart, *Buffer
  
  ScintillaSendMessage(#Scintilla, #SCI_STARTSTYLING, (*Position - *Buffer) + SciPositionStart, $1F)
  ScintillaSendMessage(#Scintilla, #SCI_SETSTYLING, Length, IdColor)
EndProcedure

Procedure ScintillaCallBack(Gadget.i, *scinotify.SCNotification)
  
  Protected SciLineNumber
  Protected txtr.TEXTRANGE
  Protected SciPositionEnd
  Shared SciPositionStart, *Buffer
  
  Select *scinotify\nmhdr\code      
      
    Case #SCN_STYLENEEDED
      SciLineNumber = ScintillaSendMessage(Gadget, #SCI_LINEFROMPOSITION, ScintillaSendMessage(Gadget, #SCI_GETENDSTYLED))
      SciPositionStart = ScintillaSendMessage(Gadget, #SCI_POSITIONFROMLINE, SciLineNumber)
      SciPositionEnd     = *scinotify\Position
      
      txtr\chrg\cpMin = SciPositionStart
      txtr\chrg\cpMax = SciPositionEnd
      txtr\lpstrText  = AllocateMemory(SciPositionEnd - SciPositionStart + 1)
      
      *Buffer          = txtr\lpstrText
      
      ScintillaSendMessage(Gadget, #SCI_GETTEXTRANGE, 0, txtr)
      
      CallFunction(#Scintilla_Highlight_DLL, "SyntaxHighlight", *Buffer, SciPositionEnd - SciPositionStart, @CallbackHighlight(), #True)
      
      FreeMemory(*Buffer)
      
  EndSelect
  
EndProcedure
;-..............Start..............
;=============================================================

; ---== MainWindow Procedures ==---------------------------------------------------------------------------------------

Procedure _dummy(ok)
  
EndProcedure

If Not OpenLibrary(#Scintilla_Highlight_DLL, #PB_Compiler_Home+"SDK/Syntax Highlighting/SyntaxHighlighting.dll") 
  MessageRequester("Error", "SyntaxHilighting.dll not found")
  End
EndIf

CompilerIf #PB_Compiler_Version < 600
If Not InitScintilla()
  MessageRequester("Error", "error Scintilla")
  End
EndIf
CompilerEndIf

Procedure MainWindowsResize_Event()
  
  xywh\w = WindowWidth(#Mainform)
  xywh\h = WindowHeight(#Mainform)
  ResizeGadget(#cmbRex, #PB_Ignore, #PB_Ignore, xywh\w - 34, 24)
  ResizeGadget(#btnTools, xywh\w - 28, #PB_Ignore, #PB_Ignore, #PB_Ignore)
  ResizeGadget(#Scintilla, #PB_Ignore, #PB_Ignore, xywh\w - 6, xywh\h - 33)
  
EndProcedure

#Menu=0
Define Resultat = CreatePopupMenu(#Menu) 
MenuItem(#CopyRef, "Copy Ref")    
MenuItem(#CopyProcRef, "Copy Proc + Ref")
MenuItem(#CopyNProcRef, "Copyr N° + Proc + Ref")
MenuBar()
MenuItem(#Copy2Declaration, "Create Declaration")
MenuBar()




; MainForm_Open()
Procedure Main()
  
  Protected tmp
  Protected  Font.s
  
  Initialization() 
  LookForWordUnderCursor()
  
  ; 	YouAreHere = FindProcedureName(CursorLine)
  If PB_ScintillaText <> ""  
    YouAreHere = FindProcedureName(CursorLine)
    If YouAreHere <> ""
      YouAreHere = "|Current: " + YouAreHere
    EndIf
  EndIf
  
  ; ini
  If OpenPreferences(ini$) 
    If PreferenceGroup("set")
      xywh\x = ReadPreferenceInteger("x", xywh\x)
      xywh\y = ReadPreferenceInteger("y", xywh\y)
      xywh\w = ReadPreferenceInteger("w", xywh\w)
      xywh\h = ReadPreferenceInteger("h", xywh\h)
    EndIf
    ClosePreferences()
  EndIf
  If xywh\x = 0 And xywh\y = 0
    centered = #PB_Window_ScreenCentered
  EndIf
  CopyStructure(@xywh, @xywh2, xywhm)
  
  
  ;- GUI
  If OpenWindow(#Mainform, xywh\x, xywh\y, xywh\w, xywh\h,
                "'" + SelectedWord + "'> "+ CountSelectedWords +" times in " + Str(ListSize(FoundReference())) + " lines" + YouAreHere,
                #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | centered)
    SetWindowColor(#Mainform, BackColor)
    StickyWindow(#Mainform, #True)
    SetWindowCallback(@Callback_Win())
    
    ComboBoxGadget(#cmbRex, 3, 3, WindowWidth(#Mainform) - 62, 24, #PB_ComboBox_Editable | #CBS_HASSTRINGS | #CBS_OWNERDRAWFIXED)
    #q$ = Chr(34)
    ;-regex
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Debug, All )\bDebug\b")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Debug, real )(?m)^\h*\KDebug\b")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# WinAPI )(?mi)[a-z][\da-z]*_(?=\h*\()")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Link )https?://[\w.:]+/?(?:[\w/?&=.~;\+!*_#%-]+)")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Procedure )(?mi)^\h*(?:Procedure[CDL$]{0,5}?(?:\h*\.[abcdfilqsuw])?\h+\K)[A-Za-z_]\w*\h*(?=\()")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Macro, All )(?mi)^\h*Macro\h+\K[A-Za-z_]\w*\h*")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Macro )(?mi)^\h*Macro\h+\K[A-Za-z_]\w*\h*(?=\()")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Var$ )(?<![#@\w])\w+\$")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# @*Point, whole )[@*]{1,2}\w+\b\$?(?![\\.(])")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# @*Point, var)[@*]{1,2}\w+(?!\()")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# @Point, Procedure)@\w+\(\)")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Hex num )(?i)\$[\da-f]+")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Comments )(?m)^\h*\K;.*?(?=\r?$)")
    ; 		
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Comments, All )(?m)^(?:[^" + #q$ + ";]*" + #q$ + "[^" + #q$ + "]*?" + #q$ + ")*[^" + #q$ + ";]*(;.*?)(?=\r?$)")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Structures, Declare )(?i)(?<![=\w" + #q$ + "\\./-])[a-z]\w*\.[a-z]\w+(?![\w" + #q$ + "\\./-])")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Structures, item )(?<![\w.:" + #q$ + "\\])\*?\w+(?:(?:\(\))?\\[\d_a-zA-Z]+)+(?![\w" + #q$ + "\\])")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Structures, Content )(?m)^\h*Structure\h*\K\w+")
    ; 		; AddGadgetItem(#cmbRex, -1, ~"(?# Comments )(?m)^(?:[^\";]*\"[^\"]*?\")*[^\";]*(;.*?)(?=\r?$)")
    ; 		; AddGadgetItem(#cmbRex, -1, ~"(?# Structures, Declare )(?i)(?<![=\\w\"\\./-])[a-z]\\w*\\.[a-z]\\w+(?![\\w\"\\\\./-])")
    ; 		; AddGadgetItem(#cmbRex, -1, ~"(?# Structures, item )(?<![\\w.:\"\\\\])\\*?\\w+(?:(?:\\(\\))?\\\\[\\d_a-zA-Z]+)+(?![\\w\"\\\\])")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Types )\b\w+\.[sfdqbliwcapu]\b")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Constants, Declare )(?m)^\h*\K#\w+\$?(?=\h*(?:=|\r?$))")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Constants, All )#\w+\b\$?")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, DECLARE )(?m)^\h*\K#[A-Z\d_]+(?=\h*(?:=|\r?$))")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, ALL )#[A-Z\d_]+\b")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, X_X )#[A-Z\d]+_[A-Z\d]+\b")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Constants, #PB_ )#PB_\w+\b\$?")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Constants, Str )#\w+\$")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# If )(?mi)^\h*\KIf(?=\h)")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Loop )(?mi)^\h*\K(For(Each)?|Repeat|While)(?=\h)")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Select )(?mi)^\h*\KSelect(?=\h)")
    ; 		AddGadgetItem(#cmbRex, -1, "(?# Include )(?mi)^\h*\KX?Include[a-z]{4,6}\b(?=\h)")
    
    ;sept 2024
    AddGadgetItem(#cmbRex, -1, "(?# Debug, All )\bDebug\b")
    AddGadgetItem(#cmbRex, -1, "(?# Debug, real )(?m)^\h*\KDebug\b")
    AddGadgetItem(#cmbRex, -1, "(?# WinAPI )(?mi)[a-z][\da-z]*_(?=\h*\()")
    AddGadgetItem(#cmbRex, -1, "(?# Link )https?://[\w.:]+/?(?:[\w/?&=.~;\+!*_#%-]+)")
    AddGadgetItem(#cmbRex, -1, "(?# Procedure )(?mi)^\h*(?:Procedure[CDL$]{0,5}?(?:\h*\.[abcdfilqsuw])?\h+\K)[A-Za-z_]\w*\h*(?=\()")
    
    ;*Mesa
    AddGadgetItem(#cmbRex, -1, "(?# Procedure Public)(?mi)^\h*(?:Procedure[CDL$]{0,5}?(?:\h*\.[abcdfilqsuw])?\h+\K)[A-Za-z]\w*\h*(?=\()")
    AddGadgetItem(#cmbRex, -1, "(?# Procedure Private)(?mi)^\h*(?:Procedure[CDL$]{0,5}?(?:\h*\.[abcdfilqsuw])?\h+\K)[_]\w*\h*(?=\()")
    
    AddGadgetItem(#cmbRex, -1, "(?# Macro )(?mi)^\h*Macro\h+\K[A-Za-z_]\w*\h*(?=\()")
    AddGadgetItem(#cmbRex, -1, "(?# Var$ )(?<![#@\w])\w+\$")
    AddGadgetItem(#cmbRex, -1, "(?# Var.Type )(?<![#@\w." + #q$ + "'])\b[a-z_]\w*\.[abcdfilqsuw]\b(?!\h*[(:])")
    ; 			AddGadgetItem(#cmbRex, -1, "(?# Var )(?<![#@\w." + #q$ + "'])\b[a-z_]\w*\b(\.[abcdfilqsuw])?(?!\h*[(:])")
    AddGadgetItem(#cmbRex, -1, "(?# @*Point, whole )[@*]{1,2}\w+\b\$?(?![\\.(])")
    AddGadgetItem(#cmbRex, -1, "(?# @*Point, var )[@*]{1,2}\w+(?!\()")
    AddGadgetItem(#cmbRex, -1, "(?# @Point, Procedure )@\w+\(\)")
    AddGadgetItem(#cmbRex, -1, "(?# ?Point )\?\w+\b")
    AddGadgetItem(#cmbRex, -1, "(?# Label: )(?mi)^\h*\w+:(?!\w)")
    AddGadgetItem(#cmbRex, -1, "(?# Hex num )(?i)\$[\da-f]+")
    AddGadgetItem(#cmbRex, -1, "(?# Comments )(?m)^\h*\K;.*?(?=\r?$)")
    AddGadgetItem(#cmbRex, -1, "(?# Comments, All )(?m)^(?:[^" + #q$ + ";]*" + #q$ + "[^" + #q$ + "]*?" + #q$ + ")*[^" + #q$ + ";]*(;.*?)(?=\r?$)")
    AddGadgetItem(#cmbRex, -1, "(?# Structures, Declare )(?i)(?<![=\w" + #q$ + "\\./-])[a-z*]\w*\.[a-z]\w+(?![\w" + #q$ + "\\./-])")
    AddGadgetItem(#cmbRex, -1, "(?# Structures, item )(?<![\w.:" + #q$ + "\\])\*?\w+(?:(?:\(\))?\\[\d_a-zA-Z]+)+(?![\w" + #q$ + "\\])")
    AddGadgetItem(#cmbRex, -1, "(?# Structures, Content )(?m)^\h*Structure\h*\K\w+")
    ; 		AddGadgetItem(#cmbRex, -1, ~"(?# Comments )(?m)^(?:[^\";]*\"[^\"]*?\")*[^\";]*(;.*?)(?=\r?$)")
    ; 		AddGadgetItem(#cmbRex, -1, ~"(?# Structures, Declare )(?i)(?<![=\\w\"\\./-])[a-z]\\w*\\.[a-z]\\w+(?![\\w\"\\\\./-])")
    ; 		AddGadgetItem(#cmbRex, -1, ~"(?# Structures, item )(?<![\\w.:\"\\\\])\\*?\\w+(?:(?:\\(\\))?\\\\[\\d_a-zA-Z]+)+(?![\\w\"\\\\])")
    AddGadgetItem(#cmbRex, -1, "(?# Types )\b\w+\.[sfdqbliwcapu]\b")
    AddGadgetItem(#cmbRex, -1, "(?# Constants, Declare )(?m)^\h*\K#\w+\$?(?=\h*(?:=|\r?$))")
    AddGadgetItem(#cmbRex, -1, "(?# Constants, All )#\w+\b\$?")
    AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, DECLARE )(?m)^\h*\K#[A-Z\d_]+(?=\h*(?:=|\r?$))")
    AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, ALL )#[A-Z\d_]+\b")
    AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, X_X )#[A-Z\d]+_[A-Z\d]+\b")
    AddGadgetItem(#cmbRex, -1, "(?# Constants, #PB_ )#PB_\w+\b\$?")
    AddGadgetItem(#cmbRex, -1, "(?# Constants, Str )#\w+\$")
    AddGadgetItem(#cmbRex, -1, "(?# If )(?mi)^\h*\KIf(?=\h)")
    ; 			AddGadgetItem(#cmbRex, -1, "(?# Loop )(?mi)^\h*\K(For(Each)?(?!ever)|Repeat|While)(?=\h+|\r?$)")
    AddGadgetItem(#cmbRex, -1, "(?# Loop )(?mi)^\h*\K(For(Each)?|Repeat|While)\b")
    AddGadgetItem(#cmbRex, -1, "(?# Loop+End )(?mi)^\h*\K(For(Each|ever)?|Repeat|While|Next|Wend|Until)\b")
    AddGadgetItem(#cmbRex, -1, "(?# Select )(?mi)^\h*\KSelect(?=\h)")
    AddGadgetItem(#cmbRex, -1, "(?# Include )(?mi)^\h*\KX?Include[a-z]{4,6}\b(?=\h)")
    AddGadgetItem(#cmbRex, -1, "(?# String )(?m)~?" + #q$ + ".*?[^\\]" + #q$)
    AddGadgetItem(#cmbRex, -1, "(?# ~String )(?m)~" + #q$ + ".*?[^\\]" + #q$)
    
    tmp = 24;= GadgetHeight(#cmbRex)
    
    ;Button
    ButtonGadget(#btnRex, WindowWidth(#Mainform) - 56,3,tmp, tmp,">")
    
    
    #img = 0
    
    
    If CreateImage(#img, tmp, tmp, 32, RGB(255, 255, 255))
      StartDrawing(ImageOutput(#img))
      Box(0, 0, tmp, tmp, BorderColor)
      Box(1, 1, tmp - 2, tmp - 2, BackColorHeader)
      DrawText((tmp - TextWidth(">")) / 2, (tmp - TextHeight(">")) / 2, "C", ForeColor, BackColorHeader)
      StopDrawing()
    EndIf
    ImageGadget(#btnTools, WindowWidth(#Mainform) - 28, 3, tmp, tmp, ImageID(0))
    GadgetToolTip(#btnTools, "Tools: Copy and misc.")
    
    If CursorLine < 1 Or CursorLine > ArraySize(Lines())
      CursorLine = 1
    EndIf
    
    ScintillaGadget(#Scintilla, 3, 30, WindowWidth(#Mainform) - 6, WindowHeight(#Mainform) - 33, @ScintillaCallBack())
    
    ; 		ScintillaSendMessage(#Scintilla, #SCI_SETLEXER, #SCLEX_CONTAINER)
    
    ;Your own PB preferences
    OpenPreferences(GetEnvironmentVariable("APPDATA") + "\PureBasic\PureBasic.prefs")
    PreferenceGroup("Editor")
    
    Font = ReadPreferenceString("EditorFontName", "Courier New")
    
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE,#STYLE_DEFAULT, $000000)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETBACK, #STYLE_DEFAULT, ReadPreferenceLong("BackgroundColor", $FFFFFF))
    
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFONT, #STYLE_DEFAULT, @Font)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETSIZE, #STYLE_DEFAULT, ReadPreferenceLong("EditorFontSize", 10))
    ScintillaSendMessage(#Scintilla, #SCI_STYLECLEARALL)
    
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Text, ReadPreferenceLong("NormalTextColor", 0))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Keyword, ReadPreferenceLong("BasicKeywordColor", $9D030D))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETBOLD, #Scintilla_Keyword, #True)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Comment, ReadPreferenceLong("CommentColor", $6F884A))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETITALIC, #Scintilla_Comment, #True)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Constant, ReadPreferenceLong("ConstantColor", $0B46AE))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_String, ReadPreferenceLong("StringColor", $413C33))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Function, ReadPreferenceLong("PureKeywordColor", $EF303D))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Asm, ReadPreferenceLong("ASMKeywordColor", $400080))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Operator,  ReadPreferenceLong("OperatorColor", $0000FF))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Structure, ReadPreferenceLong("StructureColor", $0548B4))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Number, ReadPreferenceLong("NumberColor", $0000FF))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Pointer,  ReadPreferenceLong("PointerColor", $0507B4))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Separator,  ReadPreferenceLong("SeparatorColor", $000000))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Label,  ReadPreferenceLong("LabelColor", $804000))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_Module,  ReadPreferenceLong("ModuleColor", $9D030D))
    
    ;Line nimber    
    ScintillaSendMessage(#Scintilla, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER)
    ScintillaSendMessage(#Scintilla, #SCI_SETMARGINWIDTHN, 0, 50)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETBACK, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberBackColor", GetSysColor_(15)))
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberColor", 0))
    ScintillaSendMessage(#Scintilla, #SCI_SETMARGINWIDTHN, 1, 5)
    
    ;Current line
    ScintillaSendMessage(#Scintilla, #SCI_SETCARETLINEVISIBLE, #True)
    ScintillaSendMessage(#Scintilla, #SCI_SETCARETLINEBACK, ReadPreferenceLong("CurrentLineColor", 0))
    
    ;Replace TABs by Spaces 
    ScintillaSendMessage(#Scintilla, #SCI_SETUSETABS, #False)
    
    ;TAB = 4 spaces
    ScintillaSendMessage(#Scintilla, #SCI_SETINDENT, 4)
    
    ;Indentation
    ScintillaSendMessage(#Scintilla, #SCI_SETINDENTATIONGUIDES, #SC_IV_LOOKFORWARD)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #STYLE_INDENTGUIDE, RGB(154, 205, 50))
    
    ;lexer
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETFORE, #Scintilla_MyLexer,  $0000FF)
    ScintillaSendMessage(#Scintilla, #SCI_STYLESETBOLD, #Scintilla_MyLexer, #True)
    
    RemoveKeyboardShortcut(#Mainform, #PB_Shortcut_Tab)
    
    ClosePreferences()
    
    
    ForEach FoundReference()
      FoundReference()\Reference = LTrimChar(FoundReference()\Reference, " " + #TAB$)
      
      ; >> first attempt to mark the selected word in the string
      Protected  Texte$=Str(FoundReference()\LineNo) + #TAB$ +  "["+FindProcedureName(FoundReference()\LineNo)+"]> " + FoundReference()\Reference+ #LF$;
      Protected *Texte=UTF8(Texte$)
      ScintillaSendMessage(#Scintilla, #SCI_APPENDTEXT, Len(Texte$), *Texte)    
    Next
    FreeMemory(*Texte)
    
    Define regex$ = SelectedWord
    ; ScintillaIndicColor2(UTF8(regex$), Len(regex$))
    ScintillaIndicColor(UTF8(regex$), Len(regex$),7,7)
    
    AddKeyboardShortcut(#Mainform, #PB_Shortcut_Escape, #Mainform_Shortcut_Escape_Event)
    BindEvent(#PB_Event_SizeWindow, @MainWindowsResize_Event(), #Mainform)
    
    SetActiveGadget(-1)
    
    ;Copy to clipboard
    AddKeyboardShortcut(#Mainform, #PB_Shortcut_Control | #PB_Shortcut_Shift | #PB_Shortcut_C, #Shortcut_Ctrl_Shift_C)
    ;ComboBox enter
    AddKeyboardShortcut(#Mainform, #PB_Shortcut_Return, #Shortcut_Enter)
    
    
    
    ;- Loop
    Repeat
      
      Select WaitWindowEvent()
          
        Case #PB_Event_MoveWindow
          xywh\x = WindowX(#Mainform)
          xywh\y = WindowY(#Mainform)
          
        Case #PB_Event_CloseWindow
          If Not CompareMemory(@xywh, @xywh2, SizeOf(xywhm))
            If OpenPreferences(ini$) Or CreatePreferences(ini$)
              PreferenceGroup("set")
              WritePreferenceInteger("x", xywh\x)
              WritePreferenceInteger("y", xywh\y)
              WritePreferenceInteger("w", xywh\w)
              WritePreferenceInteger("h", xywh\h)
              ClosePreferences()
            EndIf
          EndIf
          Break
          
        Case #PB_Event_Menu
          Select EventMenu()
            Case #Shortcut_Enter
              If GetActiveGadget() = #cmbRex
                flgRead = 0
                GoRegExp()
              EndIf
            Case #Shortcut_Ctrl_Shift_C
              CopyClipboard()
              
            Case #Mainform_Shortcut_Escape_Event
              Break
              
            Case #CopyRef
              CopyClipboard(#CopyRef)
            Case #CopyProcRef
              CopyClipboard(#CopyProcRef)
            Case #CopyNProcRef
              CopyClipboard(#CopyNProcRef)
            Case #Copy2Declaration
              CopyClipboard(#Copy2Declaration)
              
              
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #cmbRex
              If EventType() = #PB_EventType_Change And flgRead = 1
                flgRead = 0
                GoRegExp()
              EndIf
              
            Case #btnRex
              GoRegExp()
              
            Case #btnTools
              ; 							GoRegExp()
              ; 						  CopyClipboard()
              DisplayPopupMenu(#Menu, WindowID(#Mainform))
              
            Case #Scintilla
              If EventType() = #PB_EventType_RightClick
                
                
              Else
                JumpToLine(GetNumberLine(GetScintillaCurLineText(#Scintilla, #cmbRex)))	
              EndIf
          EndSelect
      EndSelect
    ForEver
    
  EndIf
  ProcedureReturn 0  ; not necessary, but looks good/better
EndProcedure
End main()

Create an executable and add it into the Tools menu.

M.

Re: Show all occurrences of a word in the IDE

Posted: Fri Feb 10, 2023 4:18 pm
by Allen
Hi, Mesa,

Thank you for your code, it is very useful.

Allen

Re: Show all occurrences of a word in the IDE

Posted: Fri Feb 10, 2023 4:55 pm
by AZJIO
I would also like to highlight the selected text.
viewtopic.php?f=13&t=31092&p=235655&hil ... ES#p235655

Re: Show all occurrences of a word in the IDE

Posted: Fri Feb 10, 2023 5:01 pm
by Allen
Hi,

I named the exe file as "ShowVar.exe" and add it under tool menu. After testing it for a while I found some problems.

In below code:

Code: Select all

Define.q EncodeInputF

Procedure.s ReadNextLine()
  Protected.s Tmp$
  Repeat 
    Tmp$=ReadString(1,EncodeInputF)
    If Asc(Tmp$)<>Asc(";") And Tmp$<>""
      ProcedureReturn Tmp$
    EndIf  
  Until Eof(1)
  ProcedureReturn ""
EndProcedure
1) If I highlighted the "EncodeInputF" in line 6, and run the ShowVar, line 1 and line 6 are displayed correctly. If I highlighted the "EncodeInputF" in line 1 and run SHowVar, nothing is displayed.
2) If I highlighted "Tmp$" and run ShowVar, nothing is displayed, if I only highlighted "Tmp", all lines with Tmp$ will be shown.

I am runming PB6.01 beta 2 CBE in win 10.

Allen

Re: Show all occurrences of a word in the IDE

Posted: Fri Feb 10, 2023 5:34 pm
by AZJIO
Try not to select the text, but just place the cursor on the word and everything will work out

Re: Show all occurrences of a word in the IDE

Posted: Fri Feb 10, 2023 5:38 pm
by AZJIO
ColorListIconGadget.pb

Code: Select all

#coloredChars_Delimeter = "{***\"

Enumeration
	#frmMain_References
EndEnumeration

;... Create brushes for painting item background
Structure MYBRUSHES
	brushDefault.l
	brushSelected.l
EndStructure

Global brush.MYBRUSHES

brush\brushSelected = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
brush\brushDefault = GetStockObject_(#WHITE_BRUSH)

Procedure GetCharWidth(gad, c$)
	ProcedureReturn SendMessage_(gad, #LVM_GETSTRINGWIDTH, 0, @c$)
EndProcedure

;Here we add some text to the underlying cell text to store the color info.
Procedure SetColor(gad, row, column, startp, endp, color)
	Protected text$
	If column
		text$ = GetGadgetItemText(gad, row, column)
		;Now add the new text.
		text$+#coloredChars_Delimeter+Str(startp)+"\"+Str(endp)+"\"+Str(color)
		SetGadgetItemText(gad,row,text$,column)
	EndIf
EndProcedure

Procedure myWindowCallback(hwnd, msg, wParam, lParam)
	Protected Result, *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW, subItemRect.RECT
	Protected thisRow, thisCol, subItemText$, text$, pos, i, color, j, c, c$, nextColor, thisColor
	Result = #PB_ProcessPureBasicEvents
	Dim LVColor(0)
	Select msg
		Case #WM_NOTIFY
			*nmhdr.NMHDR = lParam
			*lvCD.NMLVCUSTOMDRAW = lParam
			If *lvCD\nmcd\hdr\hwndFrom=GadgetID(#frmMain_References) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
				Select *lvCD\nmcd\dwDrawStage
					Case #CDDS_PREPAINT
						Result = #CDRF_NOTIFYITEMDRAW
					Case #CDDS_ITEMPREPAINT
						Result = #CDRF_NOTIFYSUBITEMDRAW;
					Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
						thisRow = *lvCD\nmcd\dwItemSpec
						thisCol = *lvCD\iSubItem
						If thisCol
							;... Define rect for text
							subItemRect.RECT\left = #LVIR_LABEL
							subItemRect.RECT\top = *lvCD\iSubItem
							;... Get the subitem rect
							SendMessage_(GadgetID(#frmMain_References), #LVM_GETSUBITEMRECT, thisRow, @subItemRect)
							text$ = GetGadgetItemText(#frmMain_References, thisRow, thisCol)
							pos = FindString(text$, #coloredChars_Delimeter,1)
							If pos
								subItemText$ = Left(text$, pos-1)
								text$ = Right(text$, Len(text$)-pos+1)
							Else
								subItemText$ = text$
								text$=""
							EndIf
							Dim LVColor(Len(subItemText$))
							pos=2
							For i = 1 To CountString(text$, #coloredChars_Delimeter)
								color = Val(StringField(StringField(text$,pos+2,"\"),1,"{"))
								For j = Val(StringField(text$,pos,"\")) To Val(StringField(text$,pos+1,"\"))
									LVColor(j) = color
								Next
								pos+3
							Next
							If GetGadgetState(#frmMain_References) = thisRow
								;... If item is selected
								FillRect_(*lvCD\nmcd\hdc, subItemRect, brush\brushSelected)
							Else
								;... If item is not selected
								FillRect_(*lvCD\nmcd\hdc, subItemRect, brush\brushDefault)
							EndIf
							InflateRect_(subItemRect,-2,0)

							;... Here we will paste together the colored characters
							;... to form a string. This should speed up the drawing
							For c = 1 To Len(subItemText$)
								c$ = Mid(subItemText$, c, 1)
								If thisRow <> GetGadgetState(#frmMain_References)
									For i = c + 1 To Len(subItemText$)
										thisColor = LVColor(c)
										nextColor = LVColor(i)
										If thisColor = nextColor
											c$ + Mid(subItemText$, i, 1)
											c + 1
										Else
											Break
										EndIf
									Next i
									SetTextColor_(*lvCD\nmcd\hdc, thisColor)
								Else
									SetTextColor_(*lvCD\nmcd\hdc, GetSysColor_(#COLOR_HIGHLIGHTTEXT))
								EndIf
								DrawText_(*lvCD\nmcd\hdc, c$, Len(c$), subItemRect, #DT_END_ELLIPSIS|#DT_VCENTER|#DT_SINGLELINE)
								subItemRect\left + GetCharWidth(*nmhdr\hwndFrom, c$)
							Next c
							Result = #CDRF_SKIPDEFAULT
						Else
							Result = #CDRF_DODEFAULT
						EndIf
				EndSelect
			EndIf
	EndSelect
	ProcedureReturn Result
EndProcedure

Procedure.s LTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
	Protected *memChar, *c.Character, *jc.Character
	
	If Not Asc(String$)
		ProcedureReturn ""
	EndIf
	
	*c.Character = @String$
	*memChar = @TrimChar$
	
	While *c\c
		*jc.Character = *memChar
		
		While *jc\c
			If *c\c = *jc\c
				*c\c = 0
				Break
			EndIf
			*jc + SizeOf(Character)
		Wend
		
		If *c\c
			String$ = PeekS(*c)
			Break
		EndIf
		*c + SizeOf(Character)
	Wend
	
	ProcedureReturn String$
EndProcedure
FindAllReferences2.pb

Code: Select all

;   Description: Find all references of a variable
;            OS: Windows
; English-Forum:
;  French-Forum:
;  German-Forum: http://www.purebasic.fr/german/viewtopic.php?f=8&t=28292
;-----------------------------------------------------------------------------

; MIT License
;
; Copyright (c) 2015 Kiffi
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.

; FindAllReferences



CompilerIf #PB_Compiler_OS<>#PB_OS_Windows
	CompilerError "Windows Only!"
CompilerEndIf

EnableExplicit

Enumeration ; Windows
	#frmMain
EndEnumeration
Enumeration ; Gadgets
	#frmMain_References
EndEnumeration
Enumeration ; Menu-/Toolbaritems
	#frmMain_Shortcut_Escape_Event
EndEnumeration

Global PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
If PbIdeHandle = 0 : End : EndIf

Global ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
If ScintillaHandle = 0 : End : EndIf

Procedure.s RemoveLeadingWhitespaceFromString(InString.s)

	While Left(InString, 1) = Chr(32) Or Left(InString, 1) = Chr(9)
		InString = LTrim(InString, Chr(32))
		InString = LTrim(InString, Chr(9))
	Wend

	ProcedureReturn InString

EndProcedure

Procedure.s GetScintillaText()

	Protected ReturnValue.s

	Protected length
	Protected buffer
	Protected processId
	Protected hProcess
	Protected result

	length = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)
	If length
		length + 2
		buffer = AllocateMemory(length)
		If buffer
			SendMessageTimeout_(ScintillaHandle, #SCI_GETCHARACTERPOINTER, 0, 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)
				EndIf
			EndIf
		EndIf
		FreeMemory(buffer)
	EndIf

	ProcedureReturn ReturnValue

EndProcedure

Procedure frmMain_SizeWindow_Event()
	ResizeGadget(#frmMain_References, #PB_Ignore, #PB_Ignore, WindowWidth(#frmMain) - 20, WindowHeight(#frmMain) - 20)
EndProcedure

Procedure frmMain_References_Event()

	Protected SelectedLine

	SelectedLine = Val(GetGadgetItemText(#frmMain_References, GetGadgetState(#frmMain_References), 0))

	If SelectedLine > 0
		SendMessage_(ScintillaHandle, #SCI_GOTOLINE, SelectedLine - 1, 0)
		SendMessage_(ScintillaHandle, #SCI_ENSUREVISIBLE, SelectedLine - 1, 0)
		SetForegroundWindow_(PbIdeHandle)
		SetActiveWindow_(PbIdeHandle)
	EndIf

EndProcedure

Define SelectedWord.s = GetEnvironmentVariable("PB_TOOL_Word")
If SelectedWord = "" : End : EndIf

; MessageRequester("", SelectedWord)

Define ScintillaText.s = GetScintillaText()
If ScintillaText = "" : End : EndIf

Define Line.s
Define CountLines, LineCounter
Define CountTokens, TokenCounter
Define WWE
Define RegexLines, PbRegexTokens

Structure sFoundReference
	LineNo.i
	Reference.s

EndStructure

NewList FoundReference.sFoundReference()

Dim Tokens.s(0)


;http://www.purebasic.fr/english/viewtopic.php?f=12&t=37823
RegexLines = CreateRegularExpression(#PB_Any , ".*\r\n")
PbRegexTokens = CreateRegularExpression(#PB_Any, #DOUBLEQUOTE$ + "[^" + #DOUBLEQUOTE$ + "]*" + #DOUBLEQUOTE$ + "|[\*]?[a-zA-Z_]+[\w]*[\x24]?|#[a-zA-Z_]+[\w]*[\x24]?|[\[\]\(\)\{\}]|[-+]?[0-9]*\.?[0-9]+|;.*|\.|\+|-|[&@!\\\/\*,\|]|::|:|\|<>|>>|<<|=>{1}|>={1}|<={1}|=<{1}|={1}|<{1}|>{1}|\x24+[0-9a-fA-F]+|\%[0-1]*|%|'")

CountLines = CountString(ScintillaText, #CRLF$)

Dim Lines.s(0)

CountLines = ExtractRegularExpression(RegexLines, ScintillaText, Lines())

SelectedWord = LCase(SelectedWord)

For LineCounter = 0 To CountLines - 1

	Line = Lines(LineCounter)

	CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())

	For TokenCounter = 0 To CountTokens - 1
		If SelectedWord = LCase(Tokens(TokenCounter))
			AddElement(FoundReference())
			FoundReference()\LineNo = LineCounter + 1
			Line = Trim(Line)
			Line = Mid(Line, 1, Len(Line)-2)
			FoundReference()\Reference = Line
			Break
		EndIf

	Next

Next

Define SelectedWord2.s
Define SelectedWord1.s
If ListSize(FoundReference()) = 0

	SelectedWord1 = "#" + SelectedWord

	For LineCounter = 0 To CountLines - 1

		Line = Lines(LineCounter)

		CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())

		For TokenCounter = 0 To CountTokens - 1
			If SelectedWord1 = LCase(Tokens(TokenCounter))
				AddElement(FoundReference())
				FoundReference()\LineNo = LineCounter + 1
				Line = Trim(Line)
				Line = Mid(Line, 1, Len(Line)-2)
				FoundReference()\Reference = Line
				Break
			EndIf

		Next

	Next

	If ListSize(FoundReference())
		SelectedWord = SelectedWord1
	EndIf
EndIf


If ListSize(FoundReference()) = 0

	SelectedWord2 = "*" + SelectedWord

	For LineCounter = 0 To CountLines - 1

		Line = Lines(LineCounter)

		CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())

		For TokenCounter = 0 To CountTokens - 1
			If SelectedWord2 = LCase(Tokens(TokenCounter))
				AddElement(FoundReference())
				FoundReference()\LineNo = LineCounter + 1
				Line = Trim(Line)
				Line = Mid(Line, 1, Len(Line)-2)
				FoundReference()\Reference = Line
				Break
			EndIf

		Next

	Next


	If ListSize(FoundReference())
		SelectedWord = SelectedWord2
	Else
		End
	EndIf
EndIf



XIncludeFile "ColorListIconGadget.pb"

Global hGUI
Global ColumnWidth

Procedure Redraw()
	Protected rc.RECT
		With rc
			rc\left = 10
			rc\right = ColumnWidth + 10
			rc\top = 10
			rc\bottom = 300 - 10
		EndWith
		RedrawWindow_(hGUI, rc, 0, #RDW_ERASE|#RDW_INVALIDATE|#RDW_ERASENOW)
EndProcedure

;- GUI
hGUI = OpenWindow(#frmMain,
           #PB_Ignore,
           #PB_Ignore,
           600,
           300,
           "Показать все: '" + SelectedWord + "', " + Str(ListSize(FoundReference())),
           #PB_Window_SystemMenu |
           #PB_Window_SizeGadget |
           #PB_Window_ScreenCentered)

SetWindowCallback(@myWindowCallback())

StickyWindow(#frmMain, #True)

ListIconGadget(#frmMain_References,
               10,
               10,
               WindowWidth(#frmMain) - 20,
               WindowHeight(#frmMain) - 20,
               "-№-",
               50,
               #PB_ListIcon_FullRowSelect |
               #PB_ListIcon_GridLines |
               #PB_ListIcon_AlwaysShowSelection)

AddGadgetColumn(#frmMain_References, 1, "Строка", 400)


ForEach FoundReference()
	FoundReference()\Reference = LTrimChar(FoundReference()\Reference, " " + #TAB$)
	AddGadgetItem(#frmMain_References, -1, Str(FoundReference()\LineNo) + #LF$ + FoundReference()\Reference)
Next

Define i

SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 0, #LVSCW_AUTOSIZE_USEHEADER)
SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 1, #LVSCW_AUTOSIZE)
SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 2, #LVSCW_AUTOSIZE)

AddKeyboardShortcut(#frmMain, #PB_Shortcut_Escape, #frmMain_Shortcut_Escape_Event)
BindEvent(#PB_Event_SizeWindow, @frmMain_SizeWindow_Event(), #frmMain)
BindGadgetEvent(#frmMain_References, @frmMain_References_Event())
SetActiveGadget(#frmMain_References)

ColumnWidth = GetGadgetItemAttribute(#frmMain_References, 0 , #PB_ListIcon_ColumnWidth, 0)


Define pos, le, i;, RegexClr

le = Len(SelectedWord)
i = 0

; RegexClr = CreateRegularExpression(#PB_Any , "\b\Q" + SelectedWord + "\E\b") ; проблема если в имени есть метасимволы: $ и т.д.
pos = 1
ForEach FoundReference()
	Repeat
		pos = FindString(FoundReference()\Reference, SelectedWord, pos, #PB_String_NoCase)
		If pos
			SetColor(#frmMain_References, i, 1, pos, pos + le - 1, #Red)
			pos + le
		Else
			Break
		EndIf
	ForEver

	
; 	If ExamineRegularExpression(RegexClr, FoundReference()\Reference)
; 		If NextRegularExpressionMatch(RegexClr)
; 			pos = RegularExpressionMatchPosition(RegexClr)
; 			If pos
; 				SetColor(#frmMain_References, i, 1, pos, pos + le - 1, #Red)
; 			EndIf
; 		EndIf
; 	EndIf
	i + 1
Next
Redraw()

Repeat

	WWE = WaitWindowEvent()

	If (WWE = #PB_Event_Menu And EventMenu() = #frmMain_Shortcut_Escape_Event) Or (WWE = #PB_Event_CloseWindow)
		Break
	EndIf

ForEver

DeleteObject_(brush\brushSelected)
Added the number of found lines to the title. At me 700 lines are quickly enough displayed. I wanted to add that if a lot is found, then turn off the backlight, but this works quickly.

You need to add a position to the structure so as not to search, especially since there can be 2 matches in one line, and highlighting is looking for the first one.
You need to save the position and size of the window.

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 12:43 am
by BarryG
What does this tip do? Because if I double-click any text in the IDE, all occurrences of that text get highlighted already. No need for a tool to do it.

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 2:12 am
by Allen
by AZJIO » Sat Feb 11, 2023 12:34 am

Try not to select the text, but just place the cursor on the word and everything will work out
@AZJIO, thanks. You are right. It worked a bit different from IDE.
by BarryG » Sat Feb 11, 2023 7:43 am

What does this tip do? Because if I double-click any text in the IDE, all occurrences of that text get highlighted already. No need for a tool to do it.
@BarryG, this tool will provide a summary so you need not scroll up and down to see all the occurrences in a large program. This way, you can very quickly identify any declared but unused varibles. You can also easily jump to the line by clicking on the summary window.

Allen

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 3:06 am
by AZJIO
BarryG wrote: Sat Feb 11, 2023 12:43 am What does this tip do? Because if I double-click any text in the IDE, all occurrences of that text get highlighted already. No need for a tool to do it.
Quickly jump to the desired line, such as a function call line, or to the contents of a function, or to a variable declaration. Clicking on a line moves to that line. It's best to assign this window to a hotkey, I use Ctrl+Shift+D.

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 5:11 am
by TassyJim
BarryG wrote: Sat Feb 11, 2023 12:43 am What does this tip do? Because if I double-click any text in the IDE, all occurrences of that text get highlighted already. No need for a tool to do it.
Like "Find in Files" when you only have one file in the searched folder.

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 12:27 pm
by BarryG
Thanks, guys. I set it up as tool, and I understand now. Nice!

Suggestion: Don't add a line to the list if it's already there. I had a variable used 4 times in one line, and the same line was added 4 times to the list.

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 2:12 pm
by Allen
Hi,

Is the program currently not support pointers?

Code: Select all

Define *Ptr.unicode
Define.s Text="abcd"

*Ptr=@Text
Debug *Ptr\u
I place currsor on *Ptr and nothing is shown.

Allen

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 4:23 pm
by AZJIO
BarryG wrote: Sat Feb 11, 2023 12:27 pm don't add a line to the list if it already exists
Added "Break" to the loop, now one line is added if there are several tokens in it
Allen wrote: Sat Feb 11, 2023 2:12 pm I place currsor on *Ptr and nothing is shown.
It is necessary to do in the same way as with constants an additional loop to search for pointers. Or make a proper regex. Or use original analyzer "PureBasic\SDK\Syntax Highlighting\SyntaxHighlighting.dll"

Added pointers (*Ptr etc.). But if there is the same variable in the code, then it will be highlighted, since %WORD% does not capture the characters # and *

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 5:56 pm
by Allen
AZJIO,

Thank you for the hints, I modify the code as advised ( add another loop to check pointers) and now it also worked on pointers.

Allen

Re: Show all occurrences of a word in the IDE

Posted: Sat Feb 11, 2023 6:48 pm
by AZJIO
Everything has already been done in the previous post