IDE Tool "Jump to Marker"

Working on new editor enhancements?
User avatar
Michael Vogel
Addict
Addict
Posts: 2799
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

IDE Tool "Jump to Marker"

Post by Michael Vogel »

V1.1 - added option to jump to the procedure/macro header (by holding the shift key).

Code: Select all


; Define Forum Marker Tool

	; Jump to Marker V1.1 by Michael Vogel
	; ------------------------------------

	; Example for Tool Settings:
	; --------------------------
	; Command Line: 	%COMPILEFILE\..\..\Pure\Tools\Tool Marker.exe
	; Arguments:		"%FILE" 552 "JetBrains Mono Semibold"			the second parameter sets the sizes of the window, line column and font
	; Working Dir.: 	%COMPILEFILE\..\..\Pure\Tools
	; Name: 			&Jump to Marker...
	; Event Trigger:	Menu Or Shortcut								Should be 'or' not 'Or' (the IDE should get a better 'Undo'...;)
	; Shortcut: 		Ctrl + J

	; Please set 'Enable DPI aware' compiler flag

	EnableExplicit

	#ToolExe=		1*Bool(#PB_Compiler_Debugger=#Null);				Compiled Tool Exe

	#BufferLines=	250
	#DpiBits=		12+SizeOf(Integer)
	#DpiScale=  	1<<#DpiBits

	#Background1=	$E8FFF8
	#Background2=	$E0FAF0

	Enumeration
		#File
		#True
		#Bingo
	EndEnumeration

	Enumeration
		#Win
		#Lst
		#Fnt
		#KeyGo
		#KeyExit
	EndEnumeration

	Structure LongType
		Low.l
		High.l
	EndStructure

	Structure ResultType
		StructureUnion
			Quad.q
			Long.LongType
		EndStructureUnion
	EndStructure

	Structure SourceType
		Code.s
		PLine.i
	EndStructure

	Structure ToolType
		Lines.i
		Asize.i
		Oflag.i
		Pline.i
		Width.i
		Lsize.i
		DpiScale.i
		FontSize.i
		FontName.s
		Marker.s
		SourceFile.s
	EndStructure

	Structure IdeType
		HandleIde.i
		HandleScintilla.i
		Cursor.i
		ClassTextIde.s
		TitleTextIde.s
	EndStructure

	Global Ide.IdeType
	Global Tool.ToolType

	Global Dim Source.SourceType(Tool\Asize)

	Ide\ClassTextIde=	"WindowClass_2"
	Ide\TitleTextIde=	"PureBasic"

; EndDefine

Macro ScaleUp(value)

	(((value)*Tool\DpiScale)/#DpiScale)

EndMacro
Macro ScaleDown(value)

	(((value)*#DpiScale)/Tool\DpiScale)

EndMacro

: CompilerIf #ToolExe=#Null :
Procedure.i SearchIdeHandle(hwnd.i)

	Protected ClassText.s=Space(256)

	With Ide
		If hwnd
			GetClassName_(hwnd,@classText,256)
			If classText=\ClassTextIde
				GetWindowText_(hwnd,@classText,256)
				If Not Asc(\TitleTextIde) Or FindString(classText,\TitleTextIde)
					\HandleIde=hwnd
					ProcedureReturn 0
				EndIf
			EndIf
			ProcedureReturn 1
		EndIf

		ProcedureReturn 0
	EndWith

EndProcedure
Procedure.i SearchScintilla(hwnd.i)

	Protected ClassText.s=Space(256)

	With Ide
		If hwnd
			GetClassName_(hwnd,@classText,256)
			If classText="Scintilla"
				\HandleScintilla=hwnd
				ProcedureReturn 0
			EndIf
			ProcedureReturn 1
		EndIf

		ProcedureReturn 0
	EndWith

EndProcedure
: CompilerEndIf :

Procedure.q MyTrim(*s.Character)

	Protected p,l,r,m

	Repeat
		p+1

		Select *s\c

		Case #Null
			ProcedureReturn r<<32+l+1

		Case ' ',#TAB
			If m=#Null
				l=p
			EndIf

		Default
			r=p
			If m=#Null
				m=#True
			EndIf

		EndSelect

		; Debug Str(p)+": '"+Chr(*s\c)+"'"
		*s+SizeOf(Character)

	ForEver

EndProcedure
Procedure Jump(marker)

	Protected line
	Protected Count

	; Debug "Jump to Marker #"+Chr('A'+marker)

	If GetKeyState_(#VK_SHIFT)&128
		line=GetGadgetItemData(#Lst,marker)
	EndIf
	If line=0
		line=Val(GetGadgetItemText(#Lst,marker,1))
	EndIf

	With Ide

		If \HandleIde
			SendMessage_(\HandleScintilla,#SCI_ENSUREVISIBLE,line - 1, 0)
			SendMessage_(\HandleScintilla,#SCI_GOTOLINE,line - 1, 0)
			Count=SendMessage_(\HandleScintilla,#SCI_LINESONSCREEN, 0, 0) / 2

			SendMessage_(\HandleScintilla, #SCI_SCROLLCARET, line - 1, 0)
			If Abs(\Cursor - line) < Count
				Count=0
			ElseIf \Cursor > line
				Count=-Count
			EndIf

			SendMessage_(\HandleScintilla, #SCI_LINESCROLL, 0, Count)
		EndIf

		SetForegroundWindow_(\HandleIde)
		SetActiveWindow_(\HandleIde)

	EndWith

	End

EndProcedure

Procedure ResizeWindows(h,m,w,l)

	If m=#WM_SIZING
		ResizeGadget(#Lst,#PB_Ignore,#PB_Ignore,WindowWidth(#Win),#PB_Ignore)
	EndIf

	ProcedureReturn #PB_ProcessPureBasicEvents

EndProcedure
Procedure Main()

	Protected a,i,m,n,o,p
	Protected r.ResultType
	Protected s.s,t.s


	With Ide

		CompilerIf #ToolExe
			Ide\HandleIde=Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
			Ide\HandleScintilla=Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))

		CompilerElse
			EnumChildWindows_(0,@SearchIdeHandle(),0)
			EnumChildWindows_(\HandleIde,@SearchScintilla(),0)

		CompilerEndIf

		If \HandleIde
			\Cursor=SendMessage_(\HandleScintilla,#SCI_GETCURRENTPOS, 0, 0)
			\Cursor=SendMessage_(\HandleScintilla,#SCI_LINEFROMPOSITION, \Cursor, 0)
		EndIf

	EndWith



	With Tool

		CompilerIf #PB_Compiler_Debugger
			\SourceFile="C:\Tools\Programmer\Pure\Tools\Tools\Tool Marker.pb"
		CompilerElse
			\SourceFile=ProgramParameter(0)
		CompilerEndIf

		s=ProgramParameter(1)
		If s
			n=Val(s)
		Else
			n=333
		EndIf
		\Width=250+(n/100)*100

		\Lsize=(n%100)/10
		If \Lsize
			\Lsize+4
		EndIf

		n%10
		n%10-5
		\FontSize=12+n<<Bool(n>0);	7, 8, 9, 10, 11, 12, 14, 16, 18, 20

		\FontName=ProgramParameter(2)
		If \FontName=""
			\FontName="Segoe UI"
		EndIf


		If ReadFile(#File,\SourceFile,#PB_File_SharedRead)

			While Eof(#File)=#Null
				\Lines+1

				If \Lines>\Asize
					\Asize+#BufferLines
					ReDim Source(\Asize)
				EndIf

				s=ReadString(#File)
				r\Quad=MyTrim(@s)
				s=Mid(s,r\Long\Low,r\Long\High-r\Long\Low+1)
				If Left(s,9)="Procedure" Or Left(s,6)="Macro "
					\Pline=\Lines
				EndIf

				Source(\Lines)\Code=s
				Source(\Lines)\PLine=\Pline

				If PeekC(@s)=';'
					If \Oflag=#True
						If Left(s,9)="; Markers"
							\Marker=StringField(s,2,"=")
							\Oflag=#Bingo
						EndIf
					ElseIf Left(s,20)="; IDE Options = Pure"
						\Oflag=#True
					EndIf
				EndIf


			Wend

			CloseFile(#File)

			If \Oflag=#Bingo

				\DpiScale=GetDeviceCaps_(GetDC_(0),#LOGPIXELSX)<<#DpiBits/96

				o=ScaleDown(GetSystemMetrics_(#SM_CYFULLSCREEN))-5; Just a quick workaround to show the full window

				LoadFont(#Fnt,\FontName,\FontSize)

				OpenWindow(#Win,ScaleDown(GetSystemMetrics_(#SM_CXFULLSCREEN))-\Width,0,0,0,"Jump to Marker...",#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_Invisible)
				WindowBounds(0,\Width,o,\Width,o)

				SetGadgetFont(#PB_Any,FontID(#Fnt))

				ListIconGadget(#Lst,0,0,\Width,o,"#",25,#PB_ListIcon_FullRowSelect)
				SetGadgetColor(#Lst,#PB_Gadget_BackColor,#Background1)
				AddGadgetColumn(#Lst,1,"Line",\FontSize*\Lsize*2/3)
				AddGadgetColumn(#Lst,2,"Procedure",125)
				AddGadgetColumn(#Lst,3,"Source Code",1000)

				Protected lvm.LV_COLUMN
				lvm\mask=#LVCF_FMT
				lvm\fmt=#LVCFMT_CENTER
				SendMessage_(GadgetID(#Lst),#LVM_SETCOLUMN,0,@lvm)
				lvm\fmt=#LVCFMT_RIGHT
				SendMessage_(GadgetID(#Lst),#LVM_SETCOLUMN,1,@lvm)

				AddKeyboardShortcut(#Win,#PB_Shortcut_Escape,#KeyExit)
				AddKeyboardShortcut(#Win,#PB_Shortcut_Return|#PB_Shortcut_Shift,#KeyGo)
				AddKeyboardShortcut(#Win,#PB_Shortcut_Return,#KeyGo)

				WindowBounds(0,\Width/2,o,\Width*2,o)

				\Asize=CountString(\Marker,",")+1
				For i=1 To \Asize
					n=Val(StringField(\Marker,i,","))
					If n
						If Ide\Cursor>n
							a=i
						EndIf
						p=Source(n)\PLine
						If p
							s=StringField(Source(p)\Code,2," ")
						Else
							s="-"
						EndIf
						o=Bool(PeekC(@s)='M')
						o=$E0F8FF+o*$1EFFE1

						If m<26
							t=Chr('A'+m)
						Else
							t="-"
						EndIf

						AddGadgetItem(#Lst,m,t+#LF$+Str(n)+#LF$+s+#LF$+Source(n)\Code)
						SetGadgetItemData(#Lst,m,p)
						If m&1
							SetGadgetItemColor(#Lst,m,#PB_Gadget_BackColor,#Background2)
							o-$60806
						EndIf
						SetGadgetItemColor(#Lst,m,#PB_Gadget_BackColor,o,2)
						m+1
					EndIf
				Next i

				SetWindowCallback(@ResizeWindows(),#Win)

				SetGadgetState(#Lst,a-Bool(a=m))
				SetActiveGadget(#Lst)
				StickyWindow(#Win,#True)
				HideWindow(#Win,#Null)

				Repeat
					Select WaitWindowEvent()

					Case #PB_Event_Gadget
						If EventType()=#PB_EventType_LeftDoubleClick
							Jump(GetGadgetState(#Lst))
						EndIf

					Case #PB_Event_Menu
						Select EventMenu()
						Case #KeyGo
							n=GetGadgetState(#Lst)
							If n>=0
								Jump(n)
							EndIf
						Case #KeyExit
							End
						EndSelect

					Case #WM_CHAR
						n=(EventwParam()&$CF)-'A'
						If n>=0 And n<m And n<26
							Jump(n)
						EndIf

					Case #PB_Event_CloseWindow
						End

					EndSelect

				ForEver

			EndIf
		EndIf

	EndWith

EndProcedure

Main()
Last edited by Michael Vogel on Mon Aug 11, 2025 8:10 am, edited 2 times in total.
Sergey
User
User
Posts: 54
Joined: Wed Jan 12, 2022 2:41 pm

Re: IDE Tool "Jump to Marker"

Post by Sergey »

Michael Vogel, there 2 versions of source code
Second version starts at line 412 :wink:
Thanks, useful tool
Last edited by Sergey on Thu Jul 10, 2025 5:24 pm, edited 3 times in total.
Axolotl
Addict
Addict
Posts: 813
Joined: Wed Dec 31, 2008 3:36 pm

Re: IDE Tool "Jump to Marker"

Post by Axolotl »

Interesting Idea and thanks for sharing.

As always I try to understand codes first. After that I decide to run the code or not.
So:
1, Not sure what line 298 is for. Maybe this should be Closefile()

Code: Select all

			CloseFigure_(#File)
2. My experiences with GetSystemMetrics_() are not that good.
Honestly it is not a problem with your usage, but if the result (on different flags) is negativ it fails on 64-bit.
Thats why I do the "type cast" with the procedure return.

Code: Select all

Procedure.l GetSystemMetrics(Index)            ; .l is important (works in 64-bit) .. variable can be a .i type 
  ProcedureReturn GetSystemMetrics_(Index) 
EndProcedure 
3. AFAIK there is no need for win API calls, tool could be platform independent?

Enough complaining, I'm sure you didn't want that as feedback. So thanks again for sharing.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
Michael Vogel
Addict
Addict
Posts: 2799
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: IDE Tool "Jump to Marker"

Post by Michael Vogel »

Thanks for your hints, updated the source code in the first post (took a while because the forum is not reachable in all cases).

Concerning the API function I can't remember ever seen issues with negative values but maybe with high numbers - I think a simple 'and' would be enough for such cases.

Code: Select all

Macro Long(value)
	((value)&$FFFFFFFF)
EndMacro

l=$ffffffff : Debug l

a=PeekL(@l) : Debug a

a=Long(PeekL(@l)) : Debug a
Sergey
User
User
Posts: 54
Joined: Wed Jan 12, 2022 2:41 pm

Re: IDE Tool "Jump to Marker"

Post by Sergey »

Code: Select all

CompilerIf Not #PB_Compiler_DPIAware
	MessageRequester("Warning", "Enable DPIAware", #PB_MessageRequester_Warning)
	End
CompilerEndIf
Simple check for DPIAware :wink:
User avatar
HeX0R
Addict
Addict
Posts: 1197
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: IDE Tool "Jump to Marker"

Post by HeX0R »

IDE Tools also get the handles of Scintilla and IDE from Environment variables:

Code: Select all

GetEnvironmentVariable("PB_TOOL_MainWindow")
GetEnvironmentVariable("PB_TOOL_Scintilla")
User avatar
Michael Vogel
Addict
Addict
Posts: 2799
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: IDE Tool "Jump to Marker"

Post by Michael Vogel »

Thanks, HeX0R, added.
AZJIO
Addict
Addict
Posts: 2150
Joined: Sun May 14, 2017 1:48 am

Re: IDE Tool "Jump to Marker"

Post by AZJIO »

Path dependency fixes

Code: Select all

\SourceFile="C:\Tools\Programmer\Pure\Tools\Tools\Tool Marker.pb"
replace with

Code: Select all

\SourceFile = #PB_Compiler_FilePath + #PB_Compiler_Filename
Black background

Code: Select all

#Background1 = $3F3F3F
#Background2 = $333333
Another replacement

Code: Select all

o = $E0F8FF + o * $1EFFE1
replace with

Code: Select all

o = #Background2 + o * $1EFFE1
white letters

Code: Select all

SetGadgetColor(#Lst, #PB_Gadget_FrontColor, $AAAAAA)
Post Reply