Code archives/BlitzPlus Gui/MaxIDE

This code has been declared by its author to be Public Domain code.

Download source code

MaxIDE by skidracer2006
Requires MaxGUI.
' maxide.bmx - blitzmax native integrated development environment

' released under the Blitz Shared Source Code License
' (c)2005 Blitz Research

' initial release version by simonarmstrong@blitzbasic.com

' v120d
' added external help option for linux users

' v120c
' add doc modules option to program menu and fixed syncmods so no restart required
' fixed wrong window activation ugliness in TRequester.Hide
' fixed TDebugTree.SetStack synchronization bug

' v120b
' added autobackup code to SaveSource method 
' fixed autoindent bug including tabs to the right of the cursor

' v120
' Ripped out isupdate stuff
' About requester now shows runtime BCC version

' v118
' Added file filter to SaveAs requester
' Edit method of TOpenCode now activates cursor and refreshes status
' TQuickHelp tokenizer now uses faster TToken map 
' ReadSource and WriteSource now use unicode LoadText and SaveText commands

' v112b
' added .doc file type to filters list
' added trycatch for bmxpath not found
' prepends bmx filenames loaded from help with "." to protect original source
' fixed unblanced quotes in wordatpos() stuffing up quick help 
' fixed exception when debugging function pointer values

' v112

' isupgrade - version check on ini file for ranlibdir and quick build disable
' debug step tools now respect cancontinue flag
' tidied up debug stdio buffers and flushing of process pipes
' linux defaults for closedocument-CtrlW nextdoc-AltRight prevdoc-AltLeft 
' end of lines converted to chr(13)+chr(10) for all saved source files 
' ReplaceAll uses locktextarea for speedup
' added print option for helppage
' filtering tab key in opencode for original block in/outdent
' removed vertical tabs from source
' added .bbdoc filetype to filters$
' fixed null href help tree entries (index node)
' new textareafilter code for the Ouput console emulator
' refreshes pointer in splitter on EVENT_MOUSEMOVE

' v111
' fixed open locked file not found at startup crash
' buildandrun continues from debugstop else kills task and rebuilds
' fixed bug on freshly loaded source being dirty
' fixed bug with options cancel
' MacOS specific hotkey bindings updated
' added .m to file FILTERS$
' adjusted GOTO and IDEOptions requesters

' v110
' DebugSource now calls ShowGadget on IDE window to bring debugger to front

' v109
' fixed WordAtPos to include underscore

' v108
' windows release version

' v107
' activate current panel when window receives focus
' fixed multiple lock build file bug
' fixed command highlighting for functions with # and ! return types
' sourcefile already open check now case insensitive
' block indent outdent now ctrl-[ and ctrl-]
' commandline args fixed

' v106b
' new defaults
' fixed replace all garbage
' removed extra endrem highlight

' v106
' added demo version support
' fixed delete / backspace undo redo issues
' added syntaxhighlight disable option
' fixed block indent / outdent highlighting issue
' added flushmem to replaceall loop
' set window title to full path of current document
' fixed double highlight for endrem

' v105c
' code view now includes labels etc. on first line
' textarea activated when panel open
' autohide output on exit now always returns to last active panel
' optimized code change algorithm
' like compiler, rem and endrem must be first code on line
' fixed up linux line spacing, font selection and code tree / create panel crashes
' new linux help system, style setting and popup menu support
 
' v105b
' added tabbing support in dialogs
' fixed pollsystem event debacle
' fixed lineselection out of view
' fixed highlighting for pasting code blocks
' fixed treeview memory leak and speedissues
' uses -x switch from bmk for build and run option
' debugging now opens source when stepping in

' v105
' activating window selects current panel
' fixed closing output window causing crash
' frees gadgets
' dirty flags now clears only if source=file and undobuffer=empty
' tidied up console window madness
' fixed gcc error check hang
' fixed label detection in code view
' fixed debugger crash with local block variable decls
' fixed codenode refresh with saveas

' v104
' fixed debug tree update and debugreset
' fixed incorrect navbar size for maximized window 
' added \ option
' notify gcc compiler errors in output

' v103
' navbar options left/right 
' added copy paste menu for output window
' added font color options for output and navbar windows
' fixed win32 paste from clipboard to use plain ascii
' stdio debugger handler
' save currentpanel, cursorpositions
' replace default "~\" requestfile path with a currentpath
' fixed pipe handling problem in quickhelp

' v102
' specify openfile from commandline 
' hides main window till all files openned
' checks window bounds against desktop size
' added deferred capitalizing cludge
' fixed rem/endrem updating problem
' fixed highlight / redraw noise
' drag&drop file support added
' dropdown menu in textarea added
' run with commandline arguments
' block indent/outdent
' fixed drag&drop text crash
' added escape handler to output window, removed autohide

Strict

Framework brl.maxgui

Import brl.win32maxgui
Import brl.cocoamaxgui
Import brl.fltkmaxgui

Import brl.standardio
Import brl.retro
Import brl.filesystem
Import brl.system
Import pub.freeprocess
Import brl.pngloader
Import brl.timer
Import brl.maxutil

?win32
Import "maxicons.o"
?

Incbin "icons.PNG"

Incbin "syncmodsblurb.txt"

Const IDE_VERSION$="1.20"
Global BCC_VERSION$="{unknown}"	'not valid until codeplay opened

Const EOL$="~n"
Const SPLITWIDTH=4

Const ABOUT$=..
"{bcc_version} - Copyright Blitz Research Ltd~n~n"+..
"Please visit www.blitzbasic.com for all your Blitz related needs!"

Const ABOUTDEMO$=..
"This demo features both the core BlitzMax package and optional MaxGUI module.~n~n"+..
"Please note that the MaxGUI module must be purchased separately."

Const FILTERS$="Code Files:bmx,bbdoc,txt,vp,doc,plist,bb,cpp,c,m,cxx,s,fs,vs,p,fp,glsl,h,hpp,html,htm,css,js,bat;All Files:*"

Const NodeFileTypes$="|bmx|bbdoc|cpp|cxx|c|m|h|s|fs|vs|p|fp|glsl|txt|html|js|css|bb|java|bat|ini|jpg|png|bmp|tga|wav|pl|doc|plist|"

Global MODOPTIONS$[]=["BRL","PUB","AXE"]		',"MAK","GMAN","BIRDIE"]
Global MODINFO$[]=["BlitzMax Core Modules","Public Domain Core Modules","User Contributed Modules"]	'"Mark Sibly's Module Collection","Simon Armstrong's Module Collection","Garrit Grandberg's Module Collection","Dave Bird's Module Collection"]

?MacOS
Const DEFAULTFONT$="Courier"
Const DEFAULTFONTSIZE=12
Const HOMEPAGE$="/doc/index.html"
?
?Win32
Const DEFAULTFONT$="Courier"
Const DEFAULTFONTSIZE=10
Const HOMEPAGE$="/doc/index.html"
?
?Linux
Const DEFAULTFONT$="Lucida"
Const DEFAULTFONTSIZE=12
Const HOMEPAGE$="/doc/index.html"
'Const HOMEPAGE$="/doc/home.html"
?

Const MENUNEW=1
Const MENUOPEN=2
Const MENUCLOSE=3
Const MENUSAVE=4
Const MENUSAVEAS=5
Const MENUSAVEALL=6
Const MENUPRINT=7
Const MENUQUIT=8

Const MENUUNDO=9
Const MENUREDO=10
Const MENUCUT=11
Const MENUCOPY=12
Const MENUPASTE=13
Const MENUSELECTALL=14
Const MENUGOTO=15
Const MENUINDENT=16
Const MENUOUTDENT=17
Const MENUFIND=18
Const MENUFINDNEXT=19
Const MENUREPLACE=20
Const MENUNEXT=21
Const MENUPREV=22
Const MENUBUILD=23
Const MENURUN=24

Const MENUSTEP=25
Const MENUSTEPIN=26
Const MENUSTEPOUT=27
Const MENUSTOP=28

Const MENULOCKBUILD=29
Const MENUUNLOCKBUILD=30
Const MENUBUILDMODULES=31
Const MENUBUILDALLMODULES=32

Const MENUQUICKENABLED=33
Const MENUDEBUGENABLED=34
Const MENUGUIENABLED=35

Const MENUCOMMANDLINE=36
Const MENUSYNCMODS=37
Const MENUIMPORTBB=38
Const MENUFINDINFILES=39
Const MENUPROJECTMANAGER=40
Const MENUSHOWCONSOLE=41
Const MENUOPTIONS=42

Const MENUHOME=43
Const MENUBACK=44
Const MENUFORWARD=45
Const MENUQUICKHELP=46
Const MENUABOUT=47

Const MENUNEWVIEW=48
Const MENUDOCMODS=49

Const MENUTRIGGERDOCMODS=50
Const MENUTRIGGERSYNCDOCS=51

Const MENUCLOSEALL=53

Const MENURECENT=256

Const TAB$=Chr(9)
Const QUOTES$=Chr(34)

Global TEMPCOUNT
Global is_demo
Global codeplay:TCodePlay

Function CheckDemo()
	If Not is_demo Return 1
	Notify "This feature is unavailable in the demo version of BlitzMax"
	Return 0
End Function

codeplay=New TCodePlay
codeplay.Initialize

While codeplay.running
	codeplay.poll
Wend

End

Function Quote$(a$)		'add quotes to arg if spaces found
	Local	p
	If a.length=0 Return
	If a[0]=34 Return a	'already quoted
	p=a.find(" ")
	If p=-1 Return a	'no spaces
	Return Chr(34)+a+Chr(34)		
End Function

Type TToken
	Field token$
	Field help$
	Field ref$	
	Method Create:TToken(t$,h$,r$)
		token=t
		help=h
		ref=r
		Return Self
	End Method
End Type

Type TQuickHelp
	Field map:TMap=New TMap	'key=lower(token) value=token:TToken
		
	Method AddCommand:TQuickHelp(t$,l$,a$)
		map.Insert Lower(t$),New TToken.Create(t$,l$,a$)
	End Method
	
	Method Token$(cmd$)
		Local t:TToken
		t=TToken(map.ValueForKey(cmd.toLower()))
		If t Return t.token
	End Method
	
	Method Help$(cmd$)
		Local t:TToken
		t=TToken(map.ValueForKey(cmd.toLower()))
		If t Return t.help
	End Method
	
	Method Link$(cmd$)
		Local t:TToken
		t=TToken(map.ValueForKey(cmd.toLower()))
		If t Return t.ref
	End Method
	
	Function LoadCommandsTxt:TQuickHelp(bmxpath$)
		Local	stream:TStream
		Local	qh:TQuickHelp
		Local	l$,c$,p,q
		Local	token$,help$,anchor$
		
		stream=ReadFile(bmxpath+"/doc/bmxmods/commands.txt")
		If stream=Null Return Null
		qh=New TQuickHelp
		While Not Eof(stream)
			l$=ReadLine(stream)
			Local i
			For i=0 Until l.length
				Local c=l[i]
				If c=Asc("_") Continue
				If c>=Asc("0") And c<=Asc("9") Continue
				If c>=Asc("a") And c<=Asc("z") Continue
				If c>=Asc("A") And c<=Asc("Z") Continue
				Exit
			Next
			token$=l[..i]
			help$=""
			anchor$=""
			q=l.find("|")
			If q
				help=l[..q]
				anchor=l[q+1..]
			EndIf			
			qh.AddCommand token,help,anchor
		Wend
		stream.Close
		Return qh
	End Function
End Type

Const TOOLSHOW=1
Const TOOLREFRESH=2
Const TOOLNEW=3
Const TOOLOPEN=4
Const TOOLCLOSE=5
Const TOOLSAVE=6
Const TOOLHELP=7
Const TOOLUNDO=8
Const TOOLREDO=9
Const TOOLCUT=10
Const TOOLCOPY=11
Const TOOLPASTE=12
Const TOOLQUICKSAVE=13
Const TOOLSAVEAS=14
Const TOOLGOTO=15
Const TOOLFIND=16
Const TOOLFINDNEXT=17
Const TOOLREPLACE=18
Const TOOLBUILD=19
Const TOOLRUN=20
Const TOOLLOCK=21
Const TOOLUNLOCK=22
Const TOOLSELECT=23
Const TOOLSELECTALL=24
Const TOOLINDENT=25
Const TOOLOUTDENT=26
Const TOOLACTIVATE=27
Const TOOLNAVIGATE=28
Const TOOLNEWVIEW=29
Const TOOLMENU=30
Const TOOLPRINT=31

Type TTool
	Method Invoke(command,argument:Object=Null)
	End Method
End Type

Type TRequester
	Field	host:TCodePlay
	Field	window:TGadget,ok:TGadget,cancel:TGadget
	Field	centered

	Method initrequester(owner:TCodeplay,label$,w=280,h=128,flags=3)
		host=owner
		window=CreateWindow(label,0,0,w,h,Null,1+64)
		If flags&1 cancel=CreateButton("Cancel",8,ClientHeight(window)-34,80,24,window,BUTTON_CANCEL)
		If flags&2 ok=CreateButton("OK",ClientWidth(window)-88,ClientHeight(window)-34,80,24,window,BUTTON_OK)
	End Method
	
	Method Show()
		Local	x,y,w,h,win:TGadget
		DisableGadget host.window
		If Not centered
			win=host.window		
			w=GadgetWidth(window)
			h=GadgetHeight(window)
			x=GadgetX(win)+(GadgetWidth(win)-w)/2
			y=GadgetY(win)+(GadgetHeight(win)-h)/2
			SetGadgetShape window,x,y,w,h
			centered=True
		EndIf
		ShowGadget window
		ActivateGadget window
		host.SetRequester Self
		PollSystem
	End Method
	
	Method Hide()
		EnableGadget host.window
		HideGadget window
		host.SetRequester Null
'		host.SelectPanel host.currentpanel
	End Method

	Method Poll()
	End Method
End Type

Type TProgressRequester Extends TRequester
	Field	message$,value
	Field	showing
	Field	label:TGadget
	Field	progbar:TGadget
	
	Method Show()	'returns false if cancelled
		showing=True
		Super.Show
	End Method
	
	Method Hide()
		showing=False
		Super.Hide()
	End Method
	
	Method Open(title$)
		SetGadgetText window,title
		Show
	End Method
	
	Method Update(msg$,val)
		If msg$<>message
			message=msg
			If label FreeGadget label
			label=CreateLabel(message,8,8,260,20,window)
		EndIf
		If showing And (val&$fc)<>(value&$fc)	'only update every 4 percent
			UpdateProgBar( progbar,val/100.0 )
			PollSystem
		EndIf
		value=val
	End Method
	
	Function Create:TProgressRequester(host:TCodePlay)
		Local	progress:TProgressRequester
		progress=New TProgressRequester
		progress.initrequester(host,"ProgressRequester",280,128,1)	'1 for cancel button
		progress.progbar=CreateProgBar( 8,32,260,20,progress.window )
		Return progress
	End Function
End Type

Type TPanelRequester Extends TRequester
	Field	tabber:TGadget
	Field	panels:TGadget[]
	Field	index
	
	Method InitPanelRequester(owner:TCodeplay,label$,w=280,h=128)		
		InitRequester owner,label,w,h
		w=ClientWidth(window)
		h=ClientHeight(window)-40
		tabber=CreateTabber(4,4,w-8,h-8,window)
		SetGadgetLayout tabber,1,1,1,1
	End Method

	Method SetPanelIndex(i)
		HideGadget panels[index]
		index=i
		ShowGadget panels[index]
		SelectGadgetItem tabber,index	
	End Method
	
	Method SetPanel(panel:TGadget)
		Local	p:TGadget,i
		For p=EachIn panels
			If p=panel SetPanelIndex i;Exit
			i:+1
		Next
	End Method
	
	Method AddPanel:TGadget(name$)
		Local	panel:TGadget
		panel=CreatePanel(0,0,ClientWidth(tabber),ClientHeight(tabber),tabber)
		SetGadgetLayout panel,1,1,1,1
		HideGadget panel
		AddGadgetItem tabber,name
		panels=panels[..panels.length+1]
		panels[panels.length-1]=panel
		Return panel
	End Method
	
	Method RemovePanel(panel)
	End Method
	
End Type

Type TCmdLineRequester Extends TRequester
	Field	label:TGadget,textfield:TGadget

	Method Poll()
		Local	id,data
		id=EventID()
		data=EventData()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				host.SetCommandLine TextFieldText(textfield)
				Hide				
			Case cancel
				SetGadgetText textfield,host.GetCommandLine()
				Hide
		End Select
	End Method
	
	Method Show()
		SetGadgetText textfield,host.GetCommandLine()
		Super.Show()
		ActivateGadget textfield
	End Method

	Function Create:TCmdLineRequester(host:TCodePlay)
		Local	cmd:TCmdLineRequester
		cmd=New TCmdLineRequester
		cmd.initrequester(host,"Program Command Line")
		cmd.label=CreateLabel("Program command line:",8,8,260,20,cmd.window)
		cmd.textfield=CreateTextField(8,32,260,20,cmd.window)
		Return cmd
	End Function
End Type

Type TGotoRequester Extends TRequester
	Field	linenumber:TGadget

	Method Show()
		Super.Show()
		ActivateGadget linenumber
	End Method

	Method Poll()
		Local	line,data
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				line=Int(TextFieldText(linenumber))
				Hide
				host.activepanel.Invoke TOOLGOTO,String(line)
			Case cancel
				Hide
		End Select
	End Method

	Function Create:TGotoRequester(host:TCodePlay)
		Local	seek:TGotoRequester
		seek=New TGotoRequester
		seek.initrequester(host,"Goto Line",260,128)
		CreateLabel("Line Number:",20,24,114,20,seek.window)
		seek.linenumber=CreateTextField(134,20,100,20,seek.window)
		Return seek
	End Function
End Type

Type TColor
	Field	red,green,blue

	Method Set(rgb)
		red=(rgb Shr 16)&255
		green=(rgb Shr 8)&255
		blue=rgb&255
	End Method

	Method ToString$()
		Return ""+red+","+green+","+blue
	End Method

	Method FromString(s$)
		Local	p,q
		p=s.Find(",")+1
		If Not p Return
		q=s.Find(",",p)+1
		If Not q Return
		red=Int(s[..p-1])
		green=Int(s[p..q-1])
		blue=Int(s[q..])
	End Method

	Method Request()
		If RequestColor(red,green,blue)
			red=RequestedRed()
			green=RequestedGreen()
			blue=RequestedBlue()
			Return True
		EndIf				
	End Method	
End Type

Type TTextStyle
	Field	label:TGadget,panel:TGadget,combo:TGadget
	Field	color:TColor
	Field	flags
	
	Method Set(rgb,bolditalic)
		color.set(rgb)
		flags=bolditalic
	End Method

	Method Format(textarea:TGadget,pos,length)
		FormatTextAreaText textarea,color.red,color.green,color.blue,flags,pos,length
	End Method

	Method ToString$()
		Return ""+color.red+","+color.green+","+color.blue+","+flags
	End Method

	Method FromString(s$)
		Local	p,q,r
		p=s.Find(",")+1;If Not p Return
		q=s.Find(",",p)+1;If Not q Return
		r=s.Find(",",q)+1;If Not r Return
		color.red=Int(s[..p-1])
		color.green=Int(s[p..q-1])
		color.blue=Int(s[q..r-1])
		flags=Int(s[r..])
	End Method

	Method Poll()
		Select EventSource()
			Case panel
				If EventID()=EVENT_MOUSEDOWN
					Return color.Request()
				EndIf
			Case combo
				flags=SelectedGadgetItem(combo)
				Return True
		End Select
	End Method
	
	Method Refresh()
		SetPanelColor panel,color.red,color.green,color.blue
		SelectGadgetItem combo,flags		
	End Method

	Function Create:TTextStyle(name$,xpos,ypos,window:TGadget)
		Local	s:TTextStyle
		s=New TTextStyle
		s.color=New TColor
		s.label=CreateLabel(name,xpos,ypos+4,80,24,window)
		s.panel=CreatePanel(xpos+84,ypos,24,24,window,PANEL_BORDER|PANEL_ACTIVE)
		SetPanelColor s.panel,255,255,0
		s.combo=CreateComboBox(xpos+112,ypos,96,24,window)
		AddGadgetItem s.combo,"Normal"
		AddGadgetItem s.combo,"Bold"
		AddGadgetItem s.combo,"Italic"
		AddGadgetItem s.combo,"Bold+Italic"
		Return s
	End Function
End Type

Type TGadgetStyle
	Field	label:TGadget,fpanel:TGadget,bpanel:TGadget,fbutton:TGadget
	Field	font_name$,font_size
	Field	fg:TColor
	Field	bg:TColor
	Field	font:TGUIFont

	Method Apply(gadget:TGadget)
		SetGadgetFont gadget,font
		SetGadgetColor gadget,bg.red,bg.green,bg.blue,True
		SetGadgetColor gadget,fg.red,fg.green,fg.blue,False
	End Method
	
	Method Set(fg_rgb,bg_rgb,fname$,fsize)
		fg.set(fg_rgb)
		bg.set(bg_rgb)
		font_name=fname
		font_size=fsize
	End Method

	Method ToString$()
		Return font_name+","+font_size+","+fg.ToString()+","+bg.ToString()
	End Method
	
	Function GetArg$(a$ Var)
		Local 	p,r$
		p=a.Find(",")+1
		If p=0 p=Len a$+1
		r$=a$[..p-1]
		a$=a$[p..]
		Return r$	
	End Function
	
	Method FromString(s$)		
		font_name=GetArg(s$)
		font_size=Int(GetArg(s$))
		fg.red=Int(GetArg(s$))
		fg.green=Int(GetArg(s$))
		fg.blue=Int(GetArg(s$))
		bg.red=Int(GetArg(s$))
		bg.green=Int(GetArg(s$))
		bg.blue=Int(GetArg(s$))
	End Method

	Method Poll()
		Local	f:TGUIFont
		Select EventSource()
			Case fpanel
				If EventID()=EVENT_MOUSEDOWN
					Return fg.Request()
				EndIf
			Case bpanel
				If EventID()=EVENT_MOUSEDOWN
					Return bg.Request()
				EndIf
			Case fbutton
				f=RequestFont(font)
				If f
					font_name=FontName(f)
					font_size=FontSize(f)
					Return True
				EndIf				
		End Select
	End Method
	
	Method Refresh()
		font=LoadGuiFont(font_name,font_size)
		SetPanelColor fpanel,fg.red,fg.green,fg.blue
		SetPanelColor bpanel,bg.red,bg.green,bg.blue
		SetGadgetText fbutton,font_name+":"+font_size
	End Method

	Function Create:TGadgetStyle(name$,xpos,ypos,window:TGadget)
		Local	s:TGadgetStyle
		s=New TGadgetStyle
		s.fg=New TColor
		s.bg=New TColor
		s.label=CreateLabel(name,xpos,ypos+4,56,24,window)
		s.fpanel=CreatePanel(xpos+58,ypos,24,24,window,PANEL_BORDER|PANEL_ACTIVE)
		s.bpanel=CreatePanel(xpos+86,ypos,24,24,window,PANEL_BORDER|PANEL_ACTIVE)
		s.fbutton=CreateButton("..",xpos+112,ypos,180,24,window)
		Return s
	End Function
End Type

Const NORMAL=0
Const COMMENT=1
Const QUOTED=2
Const KEYWORD=3

Type TOptionsRequester Extends TPanelRequester
' panels
	Field	optionspanel:TGadget,editorpanel:TGadget,toolpanel:TGadget
' settings
	Field	showtoolbar,restoreopenfiles,autocapitalize,syntaxhighlight,autobackup,autoindent,hideoutput,externalhelp
	Field	tabsize
	Field	editfontname$,editfontsize,editcolor:TColor
	Field	outputfontname$,outputfontsize,outputcolor:TColor
' states
	Field	editfont:TGUIFont
' gadgets
	Field	tabbutton:TGadget
	Field	editpanel:TGadget,editbutton:TGadget
	Field	buttons:TGadget[9]
	Field	styles:TTextStyle[4]
	Field	textarea:TGadget
	Field	outputstyle:TGadgetStyle
	Field	navstyle:TGadgetStyle
	Field	navswapbutton:TGadget,navswap
	Field	dirty
	Field	undo:TBank
	
	Method Snapshot()
		If Not undo undo=CreateBank(8192)
		Local stream:TStream=CreateBankStream(undo)
		write stream
		stream.close
	End Method
	
	Method Restore()
		If Not undo Return
		Local stream:TStream=CreateBankStream(undo)
		Read stream
		stream.close
	End Method

	Method SetDefaults()
		showtoolbar=True
		restoreopenfiles=True
		autocapitalize=True
		syntaxhighlight=True
		autobackup=True
		autoindent=True
		tabsize=4
		editfontname$=DEFAULTFONT
		editfontsize=DEFAULTFONTSIZE
		editcolor.set($01516b)
		styles[NORMAL].set($ffffff,0)
		styles[COMMENT].set($b1e7eb,0)
		styles[QUOTED].set($ff66,0)
		styles[KEYWORD].set($ffff00,0)
		outputstyle.set(0,-1,DEFAULTFONT,DEFAULTFONTSIZE)
		navstyle.set(0,-1,DEFAULTFONT,DEFAULTFONTSIZE)
		navswap=0
		RefreshGadgets
	End Method

	Method Write(stream:TStream)
		Local i
		stream.WriteLine "[Options]"
		stream.WriteLine "showtoolbar="+showtoolbar
		stream.WriteLine "restoreopenfiles="+restoreopenfiles
		stream.WriteLine "autocapitalize="+autocapitalize
		stream.WriteLine "syntaxhighlight="+syntaxhighlight
		stream.WriteLine "autobackup="+autobackup		
		stream.WriteLine "autoindent="+autoindent		
		stream.WriteLine "tabsize="+tabsize
		stream.WriteLine "editfontname="+editfontname		
		stream.WriteLine "editfontsize="+editfontsize		
		stream.WriteLine "editcolor="+editcolor.ToString()		
		stream.WriteLine "normal_style="+styles[0].ToString()		
		stream.WriteLine "comment_style="+styles[1].ToString()		
		stream.WriteLine "quote_style="+styles[2].ToString()		
		stream.WriteLine "keyword_style="+styles[3].ToString()		
		stream.WriteLine "output_style="+outputstyle.ToString()
		stream.WriteLine "nav_style="+navstyle.ToString()
		stream.WriteLine "nav_swap="+navswap
		stream.WriteLine "hide_output="+hideoutput
		stream.WriteLine "external_help="+externalhelp
	End Method

	Method Read(stream:TStream)
		Local	f$,p,a$,b$,t
		While Not stream.Eof()
			f$=stream.ReadLine()
			If f$="" Or (f$[..1]="[" And f$<>"[Options]") Exit
			p=f.find("=")
			a$=f[..p]
			b$=f[p+1..]
			t=Int(b)
			Select a$
				Case "showtoolbar" showtoolbar=t
				Case "restoreopenfiles" restoreopenfiles=t
				Case "autocapitalize" autocapitalize=t
				Case "syntaxhighlight" syntaxhighlight=t
				Case "autobackup" autobackup=t
				Case "autoindent" autoindent=t
				Case "tabsize" tabsize=t		
				Case "editfontname" editfontname=b
				Case "editfontsize" editfontsize=t
				Case "editcolor" editcolor.FromString(b)		
				Case "normal_style" styles[0].FromString(b)
				Case "comment_style" styles[1].FromString(b)
				Case "quote_style" styles[2].FromString(b)
				Case "keyword_style" styles[3].FromString(b)
				Case "output_style" outputstyle.FromString(b)
				Case "nav_style" navstyle.FromString(b)
				Case "nav_swap" navswap=t
				Case "hide_output" hideoutput=t
				Case "external_help" externalhelp=t
			End Select
		Wend		
		RefreshGadgets
	End Method
	
	Method RefreshGadgets()
		Local	i,rgb:TColor
		editfont=LoadGuiFont(editfontname,editfontsize)
		SetButtonState buttons[0],showtoolbar
		SetButtonState buttons[1],restoreopenfiles
		SetButtonState buttons[2],autocapitalize
		SetButtonState buttons[3],syntaxhighlight
		SetButtonState buttons[4],autobackup
		SetButtonState buttons[5],autoindent
		SetButtonState buttons[6],hideoutput
		SetButtonState buttons[7],externalhelp
		SelectGadgetItem tabbutton,Min(Max(tabsize/2-1,0),7)
		SetPanelColor editpanel,editcolor.red,editcolor.green,editcolor.blue
		SetGadgetText editbutton,editfontname+":"+editfontsize
		For i=0 To 3
			styles[i].Refresh
		Next
		LockTextArea textarea
		SetTextAreaColor textarea,editcolor.red,editcolor.green,editcolor.blue,True
		SetGadgetFont textarea,editfont
		styles[0].format(textarea,0,-1)
		styles[1].format(textarea,0,17)
		styles[2].format(textarea,26,8)
		styles[3].format(textarea,36,5)
		UnlockTextArea textarea
		outputstyle.Refresh
		navstyle.Refresh
		SelectGadgetItem navswapbutton,Min(Max(navswap,0),1)
		dirty=True
	End Method

	Method Poll()
		Local	i,font:TGUIFont,refresh
		For i=0 To 3
			refresh=refresh|styles[i].Poll()
		Next
		refresh=refresh|outputstyle.Poll()
		refresh=refresh|navstyle.Poll()
		If EventSource()=buttons[0] showtoolbar=ButtonState(buttons[0]);dirty=True
		If EventSource()=buttons[1] restoreopenfiles=ButtonState(buttons[1])
		If EventSource()=buttons[2] autocapitalize=ButtonState(buttons[2]);dirty=True
		If EventSource()=buttons[3] syntaxhighlight=ButtonState(buttons[3]);dirty=True
		If EventSource()=buttons[4] autobackup=ButtonState(buttons[4])
		If EventSource()=buttons[5] autoindent=ButtonState(buttons[5])
		If EventSource()=buttons[6] hideoutput=ButtonState(buttons[6])
		If EventSource()=buttons[7] externalhelp=ButtonState(buttons[7])
		Select EventSource()
			Case tabber
				SetPanelIndex SelectedGadgetItem(tabber)
			Case ok
				Hide
				If dirty host.RefreshAll
				dirty=False
				SnapShot
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Restore
					dirty=False
					Hide
				EndIf
			Case cancel
				Restore
				dirty=False
				Hide
			Case tabbutton
				tabsize=(SelectedGadgetItem(tabbutton)+1)*2
				refresh=True
			Case editpanel
				If EventID()=EVENT_MOUSEDOWN
					refresh=editcolor.Request()
				EndIf
			Case editbutton
				font=RequestFont(editfont)
				If font
					editfontname=FontName(font)
					editfontsize=FontSize(font)
					refresh=True
				EndIf
			Case navswapbutton
				navswap=SelectedGadgetItem(navswapbutton)
				refresh=True
		End Select
		If refresh RefreshGadgets
	End Method
	
	Method InitOptionsRequester(host:TCodePlay)		
		Local	w:TGadget
'		o=New TOptionsRequester
		InitPanelRequester(host,"Options",320,440)
' init values
		editcolor=New TColor
' init gadgets
		optionspanel=AddPanel("Options")
		editorpanel=AddPanel("Editor")
		toolpanel=AddPanel("Tools")

		w=optionspanel
		buttons[0]=CreateButton("Show ToolBar",10,10,280,24,w,2)
		buttons[1]=CreateButton("Open Files At Startup",10,34,280,24,w,2)
		buttons[2]=CreateButton("Auto Capitalize",10,58,280,24,w,2)
		buttons[3]=CreateButton("Syntax Highlighting",10,82,280,24,w,2)
		buttons[4]=CreateButton("Auto Backup",10,106,280,24,w,2)
		buttons[5]=CreateButton("Auto Indent",10,130,280,24,w,2)
		buttons[6]=CreateButton("Hide Output When Process Complete",10,154,280,24,w,2)
		buttons[7]=CreateButton("Use External Help Browser",10,178,280,24,w,2)

		w=editorpanel
		CreateLabel("Background",4,12+4,80,24,w)
		editpanel=CreatePanel(88,12,24,24,w,PANEL_BORDER|PANEL_ACTIVE)
		editbutton=CreateButton("..",116,12,180,24,w)

		styles=New TTextStyle[4]
		styles[0]=TTextStyle.Create("PlainText:",4,40,w)
		styles[1]=TTextStyle.Create("Remarks:",4,68,w)
		styles[2]=TTextStyle.Create("Strings:",4,96,w)
		styles[3]=TTextStyle.Create("KeyWords:",4,124,w)		
		
		tabbutton=CreateComboBox(20,180,128,24,w)
		For Local i=1 To 8
			AddGadgetItem tabbutton,"TabSize="+(i*2)
		Next
		
		textarea=CreateTextArea(10,220,ClientWidth(w)-20,140,w,TEXTAREA_READONLY)
		SetTextAreaText textarea,"' Example Listing~n~nname$=~qBlitzMax~q~nPrint name$~n"

		w=toolpanel
		outputstyle=TGadgetStyle.Create("Output",4,12,w)
		navstyle=TGadgetStyle.Create("Navbar",4,40,w)

		navswapbutton=CreateComboBox(20,66,128,24,w)
		AddGadgetItem navswapbutton,"Navbar on right"
		AddGadgetItem navswapbutton,"Navbar on left"

		SetDefaults()
		SetPanel optionspanel
		
		SnapShot
	End Method
	
	Function Create:TOptionsRequester(host:TCodePlay)
		Local	o:TOptionsRequester
		o=New TOptionsRequester
		o.InitOptionsRequester host
		Return o
	End Function
	
End Type

Type TFindRequester Extends TRequester
	Field	findterm:TGadget
	
	Method ShowFind(term$="")
		If term SetGadgetText(findterm,term)
		Super.Show()
		ActivateGadget findterm
	End Method

	Method Poll()
		Local	find$,data		
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf				
			Case ok
				find=TextFieldText(findterm)
				Hide
				PollSystem
				host.activepanel.Invoke TOOLFINDNEXT,find
			Case cancel
				Hide
		End Select
	End Method

	Function Create:TFindRequester(host:TCodePlay)
		Local	seek:TFindRequester
		seek=New TFindRequester
		seek.initrequester(host,"Find",280,128)
		CreateLabel("Find What",8,16,80,24,seek.window)
		seek.findterm=CreateTextField(88,12,180,20,seek.window)
		Return seek
	End Function
End Type

Type TReplaceRequester Extends TRequester
	Field	findterm:TGadget,replaceterm:TGadget
	Field	findnext:TGadget,replaceit:TGadget,replaceall:TGadget
	
	Method Show()
		Super.Show()
		ActivateGadget findterm
	End Method

	Method Poll()
		Local	find$,Replace$
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				Hide
			Case cancel
				Hide
			Case findnext
				find=TextFieldText(findterm)
				host.activepanel.Invoke TOOLFINDNEXT,find
			Case replaceit
				Replace=TextFieldText(replaceterm)
				If host.activepanel.Invoke(TOOLREPLACE,Replace)
					host.activepanel.Invoke TOOLFINDNEXT,find
				EndIf				
			Case replaceall
				find=TextFieldText(findterm)
				Replace=TextFieldText(replaceterm)
				host.activepanel.Invoke TOOLREPLACE,find+Chr(0)+Replace
		End Select
	End Method

	Function Create:TReplaceRequester(host:TCodePlay)
		Local x,y
		Local	seek:TReplaceRequester
		seek=New TReplaceRequester
		seek.initrequester(host,"Find and Replace",380,200)
		
		y=14
		CreateLabel( "Find What",8,y+4,88,24,seek.window )
		seek.findterm=CreateTextField( 96,y,168,20,seek.window )

		y:+32		
		CreateLabel( "Replace With",8,y+4,88,24,seek.window )
		seek.replaceterm=CreateTextField( 96,y,168,20,seek.window )

		x=ClientWidth(seek.window)-104
		y=12
		seek.findnext=CreateButton("Find Next",x,y,96,24,seek.window)
		seek.replaceit=CreateButton("Replace",x,y+32,96,24,seek.window)
		seek.replaceall=CreateButton("Replace All",x,y+64,96,24,seek.window)
		Return seek
	End Function
End Type

Type TSyncModsRequester Extends TRequester
	Field	label:TGadget,user:TGadget,password:TGadget,proxy:TGadget
	Field	options:TGadget[]

	Method SyncMods()
		Local	u$,p$,x$,cmd$,i,n
		u$=quote(TextFieldText(user))
		p$=quote(TextFieldText(password))
		x$=TextFieldText(proxy)
		cmd$=quote(host.bmxpath+"/bin/syncmods")
		cmd$:+" -u "+u$+" -p "+p$
		If x cmd$:+" -y "+x
		n=MODOPTIONS.length
		For Local i=0 Until n
			If ButtonState(options[i]) cmd$:+" "+MODOPTIONS[i]
		Next			
		Hide
		host.execute cmd,"Synchronize Modules"',MENUTRIGGERDOCMODS
	End Method
	
	Method Poll()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				SyncMods
			Case cancel
				Hide
		End Select
	End Method
	
	Method Show()
		Super.Show()
		ActivateGadget user
	End Method

	Function Create:TSyncModsRequester(host:TCodePlay)
		Local	sync:TSyncModsRequester
		Local m$
		
		m$=LoadString("incbin::syncmodsblurb.txt")
		
		sync=New TSyncModsRequester
		sync.initrequester(host,"Synchronize modules",420,420)

'		sync.label=CreateLabel(m$,8,20,380,160,sync.window)
		sync.label=CreateTextArea(8,8,400,160,sync.window,TEXTAREA_READONLY|TEXTAREA_WORDWRAP)
		SetGadgetText sync.label,m$
		
		Local i,n,y

		y=180
		
		CreateLabel("Username",20,y+4,80,24,sync.window)
		sync.user=CreateTextField(108,y,160,20,sync.window)
		y:+30

		CreateLabel("Password",20,y+4,80,24,sync.window)
		sync.password=CreateTextField(108,y,160,20,sync.window,TEXTFIELD_PASSWORD)		
		y:+30

		CreateLabel("Proxy Server",20,y+4,80,24,sync.window)
		sync.proxy=CreateTextField(108,y,160,20,sync.window)		
		y:+30
		
		n=MODOPTIONS.length
		sync.options=New TGadget[n]
		For Local i=0 Until n
			sync.options[i]=CreateButton(MODOPTIONS[i],20,y,60,24,sync.window,BUTTON_CHECKBOX)
			If i<2 
				SetButtonState sync.options[i],True
				DisableGadget sync.options[i]
			EndIf
			CreateLabel MODINFO[i],80,y+4,220,24,sync.window
			y:+26
		Next
				
		Return sync
	End Function
	
	Function GetArg$(a$ Var)
		Local 	p,r$
		p=a.Find(",")+1
		If p=0 p=Len a$+1
		r$=a$[..p-1]
		a$=a$[p..]
		Return r$	
	End Function

	Function Crypt$(a$)
		Local b$,c:Byte,i
		For i=0 Until Len a
			c=a[i]
			If c>63 And c<192 c:~(i*-41)&63
			b:+Chr(c)
		Next
		Return b
	End Function
			
	Method FromString(s$)
		Local a$,i,n	
		SetGadgetText user,GetArg(s$)
		SetGadgetText password,Crypt(GetArg(s$))
		SetGadgetText proxy,GetArg(s$)
		n=MODOPTIONS.length
		While s$
			a$=GetArg(s$)
			For Local i=2 Until n
				If a$=MODOPTIONS[i] SetButtonState options[i],True
			Next
		Wend
	End Method
	
	Method ToString$()
		Local sync$,i,n
		sync=TextFieldText(user)
		sync:+","+Crypt(TextFieldText(password))
		sync:+","+TextFieldText(proxy)
		n=MODOPTIONS.length
		For Local i=2 Until n
			If ButtonState(options[i]) sync:+","+MODOPTIONS[i]
		Next
		Return sync
	End Method
End Type

Type TEventHandler Extends TTool
	Method OnEvent() Abstract
End Type

Type TSplitter Extends TEventHandler
	Const	HORIZONTAL=0
	Const	VERTICAL=1

	Field	axis,gadget0:TGadget,gadget1:TGadget,group:TGadget
	Field	panel:TGadget,pos,flipped,snap,oldpos,oldsize
	
	Method Position(p)
		Move p-pos
	End Method
		
	Method Move(d)
		Local	w,h,p
		pos:+d
		w=ClientWidth(group)
		h=ClientHeight(group)
		If pos<0 pos=0
		If axis=VERTICAL
			If pos>w-SPLITWIDTH pos=w-SPLITWIDTH
			If (d<0)~flipped
				SetGadgetShape gadget0,0,0,pos-SPLITWIDTH,h
				SetGadgetShape panel,pos-SPLITWIDTH,0,SPLITWIDTH*2,h
				SetGadgetShape gadget1,pos+SPLITWIDTH,0,w-(pos+SPLITWIDTH),h
			Else
				SetGadgetShape gadget1,pos+SPLITWIDTH,0,w-(pos+SPLITWIDTH),h
				SetGadgetShape panel,pos-SPLITWIDTH,0,SPLITWIDTH*2,h
				SetGadgetShape gadget0,0,0,pos-SPLITWIDTH,h
			EndIf
		Else
			If pos>h-SPLITWIDTH pos=h-SPLITWIDTH
			If (d<0)~flipped
				SetGadgetShape gadget0,0,0,w,pos-SPLITWIDTH
				SetGadgetShape panel,0,pos-SPLITWIDTH,w,SPLITWIDTH*2
				SetGadgetShape gadget1,0,pos+SPLITWIDTH,w,h-(pos+SPLITWIDTH)
			Else
				SetGadgetShape gadget1,0,pos+SPLITWIDTH,w,h-(pos+SPLITWIDTH)
				SetGadgetShape panel,0,pos-SPLITWIDTH,w,SPLITWIDTH*2
				SetGadgetShape gadget0,0,0,w,pos-SPLITWIDTH
			EndIf
		EndIf
	End Method
	
	Method Resize()
		If axis=VERTICAL
			pos=GadgetX(panel)+SPLITWIDTH
			If pos<0 Or pos>ClientWidth(group) move(0)
		Else
			pos=GadgetY(panel)+SPLITWIDTH
			If pos<0 Or pos>ClientHeight(group) move(0)
		EndIf
	End Method		
	
	Method OnEvent()
		If EventSource()<>panel Return
		Select EventID()
			Case EVENT_MOUSEDOWN
				snap=True
				If axis
					oldpos=EventX()
				Else
					oldpos=EventY()
				EndIf				
			Case EVENT_MOUSEENTER
				If axis
					SetPointer POINTER_SIZEWE
				Else
					SetPointer POINTER_SIZENS
				EndIf
			Case EVENT_MOUSELEAVE
				SetPointer POINTER_DEFAULT
			Case EVENT_MOUSEUP
				snap=False
			Case EVENT_MOUSEMOVE
				If axis
					SetPointer POINTER_SIZEWE
				Else
					SetPointer POINTER_SIZENS
				EndIf	
				If snap
					If axis
						Move EventX()-oldpos
					Else
						Move EventY()-oldpos
					EndIf
				EndIf							
		End Select
	End Method
	
	Method SetFlip(f,init=True)
		Local	t:TGadget
		If f<>flipped
			flipped=f
			t=gadget0;gadget0=gadget1;gadget1=t
			If init 
				If axis=VERTICAL
					pos=ClientWidth(group)-pos-1
				Else
					pos=ClientHeight(group)-pos-1
				EndIf
			EndIf
		EndIf			
		If axis
			If flipped
				SetGadgetLayout gadget0,1,0,1,1
				SetGadgetLayout gadget1,1,1,1,1
				SetGadgetLayout panel,1,0,1,1
			Else
				SetGadgetLayout gadget0,1,1,1,1
				SetGadgetLayout gadget1,0,1,1,1
				SetGadgetLayout panel,0,1,1,1
			EndIf
		Else
			If flipped
				SetGadgetLayout gadget0,1,1,1,0
				SetGadgetLayout gadget1,1,1,1,1
				SetGadgetLayout panel,1,1,1,0
			Else
				SetGadgetLayout gadget0,1,1,1,1
				SetGadgetLayout gadget1,1,1,0,1
				SetGadgetLayout panel,1,1,0,1
			EndIf
		EndIf
		Position pos
	End Method

	Function Create:TSplitter(axis,pos,flipped,gadget0:TGadget,gadget1:TGadget)
		Local	s:TSplitter		
		s=New TSplitter
		s.axis=axis
		s.gadget0=gadget0
		s.gadget1=gadget1
		s.group=GadgetGroup(gadget0)
		s.panel=CreatePanel(0,0,0,0,s.group,PANEL_ACTIVE)'|PANEL_BORDER)
		s.pos=pos
		s.setflip flipped,False
		Return s
	End Function
End Type

Type TToolPanel Extends TEventHandler
	Field	name$,path$
	Field	panel:TGadget
	Field	index
	Field	active
	
	Method Show()
	End Method
End Type

Type TView
	Field	node:TGadget,state
End Type

Type TNode Extends TTool
	Const	HIDESTATE=0
	Const	CLOSEDSTATE=1
	Const	OPENSTATE=2

	Field	name$,sortname$
	Field	parent:TNode
	Field	kids:TList=New TList
	Field	views:TView[]
' activate program	
	Field	target:TTool
	Field	action
	Field	argument:Object

	Method SortKids( ascending=True )
		Local term:TLink=kids._head
		Repeat
			Local link:TLink=kids._head._succ
			Local sorted=True
			Repeat
				Local succ:TLink=link._succ
				If succ=term Exit
				Local cc=TNode(link._value).sortname.Compare( TNode(succ._value).sortname )
				If (cc>0 And ascending) Or (cc<0 And Not ascending)
					Local link_pred:TLink=link._pred
					Local succ_succ:TLink=succ._succ
					link_pred._succ=succ
					succ._succ=link
					succ._pred=link_pred
					link._succ=succ_succ
					link._pred=succ
					succ_succ._pred=link
					sorted=False
				Else
					link=succ
				EndIf
			Forever
			If sorted Return
			term=link
		Forever
	End Method

	Method FindArgument:TNode(arg:Object)
		Local	n:TNode,r:TNode,a$
		If arg.Compare(argument)=0 Return Self
		a$=(String(arg)).ToLower()
		If a And a=(String(argument)).toLower() Return Self
		For n=EachIn kids
			r=n.FindArgument(arg)
			If r Return r
		Next
	End Method
	
	Method Dump(indent$="")
		Local	n:TNode		
		Print indent+name
		indent:+"~t"
		For n=EachIn kids
			n.Dump indent
		Next
	End Method		
	
	Method IsHidden()
		Local	v:TView
		If Not parent Return False
		For v=EachIn parent.views
			If v.state=OPENSTATE Return False
		Next
		Return True
	End Method
	
	Method SetAction(tool:TTool,cmd,arg:Object=Null)
		target=tool
		action=cmd
		argument=arg
	End Method

	Method Hide(v:TView=Null)	'null means hide in all views
		Local	n:TNode
		For n=EachIn kids
			n.hide v
		Next
		If v
			If v.node FreeTreeViewNode v.node;v.node=Null
		Else
			For v=EachIn views
				If v.node FreeTreeViewNode v.node;v.node=Null
			Next
		EndIf
	End Method
	
	Method Detach()
		Hide
		If parent parent.kids.remove Self
		parent=Null
	End Method

	Method FreeKids()
		Local	n:TNode		
		For n=EachIn kids
			n.free
		Next
	End Method
			
	Method Free()
		Local	n:TNode		
		For n=EachIn kids
			n.free
		Next
		Detach		'Hide()
		views=Null
	End Method
	
	Method Invoke(command,arg:Object=Null)
		Select command
		Case TOOLACTIVATE 
			If target Return target.Invoke(action,argument)
		End Select
	End Method
	
	Method Find:TNode(treeviewnode:TGadget,view=0)
		Local	n:TNode,r:TNode
		Local	v:TView
		v=getview(view)
		If v And v.node=treeviewnode Return Self
		For n=EachIn kids
			r=n.Find(treeviewnode,view)
			If r Return r
		Next
	End Method
	
	Method SetNode(treeviewnode:TGadget,view=0)
		Local	v:TView
		v=getview(view)
		v.node=treeviewnode
		open view
	End Method
	
	Method HighLight(view=-1)
		Local	v:TView
		If view=-1
			For view=0 To views.length
				HighLight view
			Next
			Return
		EndIf
		v=GetView(view)
		If v.node SelectTreeViewNode v.node
	End Method
	
	Method Open(view=-1)
		Local	v:TView
		If view=-1
			For view=0 To views.length
				Open view
			Next
			Return
		EndIf
		v=GetView(view)
		If v.state<>OPENSTATE
			v.state=OPENSTATE
			RefreshView view
'			if v.node ExpandTreeViewNode v.node
		EndIf
	End Method
	
	Method Close(view=0)
		Local	v:TView
		v=GetView(view)
		If v.state<>CLOSEDSTATE
			v.state=CLOSEDSTATE
'			if v.node CollapseTreeViewNode v.node
		EndIf
	End Method
	
	Method GetState(view=0)
		Local	v:TView
		v=GetView(view)
		Return v.state
	End Method

	Method GetView:TView(view=0)
		If view>=views.length 
			views=views[..view+1]
			views[view]=New TView
		EndIf
		If views[view]=Null views[view]=New TView
		Return views[view]
	End Method
	
	Method GetIndex()
		Local	node:TNode
		Local	i		
		If parent
			For node=EachIn parent.kids
				If node=Self Return i
				i:+1
			Next
		EndIf
	End Method
	
	Method Refresh()
		Local	i
		For i=0 To views.length-1
			RefreshView i
		Next
	End Method
	
	Method RefreshView(view=0)
		Local	n:TNode,quick
		Local	v:TView,vv:TView
		Local	node
		If parent And parent.getstate(view)=CLOSEDSTATE quick=True		
		v=getview(view)
		If v.node And parent
			ModifyTreeViewNode v.node,name
		Else
			If parent And name
				vv=parent.getview(view)
				If vv.node
'					v.node=AddTreeViewNode(name,vv.node)
					v.node=InsertTreeViewNode(GetIndex(),name,vv.node)
					If v.state=HIDESTATE v.state=CLOSEDSTATE					
					If vv.state=OPENSTATE ExpandTreeViewNode vv.node
					quick=False
				EndIf
			EndIf
		EndIf
		If quick Return
		If Not kids Return
		For n=EachIn kids
			n.RefreshView view
		Next
	End Method

	Method NodeAfter:TNode(node:TNode)
		Local	link:TLink
		If node	link=kids.FindLink(node)
		If link link=link.NextLink()
		If link Return TNode(link.Value())	
	End Method

	Method Sync(snap:TNode)
		Local	snapkid:TNode
		Local	currentkid:TNode
		Local	kid:TNode
		Local	t:TNode
		Local	link:TLink

		If snap.name<>name Return
		If kids.Count() currentkid=TNode(kids.First())
		For snapkid=EachIn snap.kids
' if same name in list 
			kid=currentkid
			While kid
				If kid.name=snapkid.name Exit
				kid=NodeAfter(kid)
			Wend
' then remove entries in front			
			If kid
				While currentkid<>kid
					t=currentkid
					currentkid=NodeAfter(currentkid)			
					t.free()
				Wend
			EndIf
' if same name sync else insert 
			If currentkid And currentkid.name=snapkid.name	'merge values if same name 
				currentkid.Sync snapkid
				currentkid=NodeAfter(currentkid)
			Else
				snapkid.detach
				If currentkid
					link=kids.FindLink(currentkid)
					kids.InsertBeforeLink snapkid,link
				Else
					kids.AddLast snapkid
				EndIf
				snapkid.parent=Self
			EndIf
		Next
' remove any entries at end
		While currentkid
			t=currentkid
			currentkid=NodeAfter(currentkid)			
			t.free()
		Wend
		Refresh()
	End Method

	Method SetName(n$)
		name=n
	End Method
		
	Method AddNode:TNode(name$)
		Local	v:TNode
		v=New TNode
		v.setname name
		Append v
		Return v
	End Method
	
	Method Append(v:TNode)
		v.parent=Self
		kids.AddLast v
	End Method	
	
	Function Create:TNode(name$)
		Local	node:TNode
		node=New TNode
		node.setname name
		Return node
	End Function		
End Type

Type THelpPanel Extends TToolPanel

	Field	host:TCodePlay
	Field	htmlview:TGadget
	Field root:TNode
	Field user:TNode
	Field  lang:TNode
	Field mods:TNode

	Method AddLink:TNode(parent:TNode,name$,href$)
		Local	n:TNode
		n=parent.AddNode(name)
		If href href=RealPath(href)
		n.SetAction(Self,TOOLNAVIGATE,href)
		Return n
	End Method
	
	Method ImportLinks(root:TNode,path$)
		Local	stream:TStream
		Local	c$,l$,p,q,a$,n$,cat
		Local	node:TNode
		
		stream=ReadFile(path)
		If Not stream Return
		path=ExtractDir(path)
		node=root
		While Not Eof(stream)
			c=ReadLine(stream)
			If c="" Continue
			If c.Find("Alphabetic index")<>-1
				node=AddLink(root,"Index","")
				Continue
			EndIf
			l=c.ToLower()
			l=l.Replace(QUOTES$,"'")
			p=l.Find("<a")
			If p=-1 Continue
			a$=""
			q=l.find("href=",p)+1
			If q
				If l[q+4]=39	'"'"
					p=q+5
					q=l.find("'",p)
				Else
					p=q+4
					q=l.find(" ",p)
				EndIf
				If q>p 
					a$=path+"/"+c[p..q]
				EndIf
			EndIf
			p=c.Find(">",q)+1
			If p And c[p]=60 p=c.Find(">",p)+1
			q=c.Find("<",p)
			If q<=p Continue
			n$=c[p..q]
'			print n$
			If l.find("onclick=toggle")<>-1
				node=AddLink(root,n$,a$)
			Else
				AddLink(node,n$,a$)
			EndIf
		Wend
		stream.Close
	End Method
	
	Method SyncDocs()
		mods.FreeKids
		AddLink(mods,"Welcome",host.bmxpath+"/doc/bmxmods/welcome.html")
		ImportLinks mods,host.bmxpath+"/doc/bmxmods/navbar.html"
		mods.Refresh
	End Method

	Method BuildTree()
		root=host.helproot
		user=root.AddNode("UserGuide")
		ImportLinks user,host.bmxpath+"/doc/bmxuser/navbar.html"
		lang=root.AddNode("Language")
		ImportLinks lang,host.bmxpath+"/doc/bmxlang/navbar.html"
		mods=root.AddNode("Modules")
		SyncDocs
		AddLink root,"Samples",host.bmxpath+"/samples/index.html"
		root.refresh
	End Method

	Method Invoke(command,argument:Object=Null)
		Local	href$
		If Not htmlview Return
		Select command
			Case TOOLCUT
				GadgetCut htmlview
			Case TOOLCOPY
				GadgetCopy htmlview
			Case TOOLPASTE
				GadgetPaste htmlview
			Case TOOLSHOW 
				ActivateGadget htmlview	
				host.SetTitle
			Case TOOLNAVIGATE
				href$=String(argument)
				If href Go href
			Case TOOLPRINT
				GadgetPrint htmlview
		End Select
	End Method

	Method OnEvent()
		Local	url$,p,t$
		If EventSource()=htmlview
			Select EventID()			
				Case EVENT_GADGETACTION				'NAVIGATEREQUEST
					url$=String( EventExtra() )
					If url[..5]="http:"
						OpenURL url
					Else
						p=url.findlast(".")
						If p>-1
							t$=url[p..].tolower()
							If t$=".bmx"
								If url.Find( "file://" )=0
									url=url[7..]
									?Win32
									url=url[1..]
									?
								EndIf 
								url=url.replace("%20"," ")
								Local source:TOpenCode=host.OpenSource(url)
								If source source.MakePathTemp
							Else 
								url=url.Replace("\","/")
								url=url.Replace("user/index","user/welcome")
								url=url.Replace("lang/index","lang/welcome")
								url=url.Replace("mods/index","mods/welcome")
								Go url$
							EndIf
						EndIf
					EndIf
			End Select			
		EndIf
	End Method
	
	Method Go(url$,internal=False)
		Local	node:TNode

		If host.options.externalhelp And Not internal
			PollSystem
			OpenURL url
			MinimizeWindow host.window
			PollSystem
			Return
		EndIf

		HtmlViewGo htmlview,url$
		host.SelectPanel Self
		node=host.helproot.FindArgument(RealPath(url))
		If node
			node.Highlight
		Else
'			print "node not found"
		EndIf		
		ActivateGadget htmlview			
	End Method
	
	Method Home()
		Go host.bmxpath+HOMEPAGE,True
	End Method
	
	Method Forward()
		HtmlViewForward htmlview
	End Method

	Method Back()
		HtmlViewBack htmlview
	End Method

	Function Create:THelpPanel(host:TCodePlay)
		Local	p:THelpPanel
		Local	root,style		
		p=New THelpPanel
		p.host=host
		p.name="Help"
		codeplay.addpanel(p)
		style=HTMLVIEW_NONAVIGATE		'HTMLVIEW_NOCONTEXTMENU
		p.htmlview=CreateHTMLView(0,0,ClientWidth(p.panel),ClientHeight(p.panel),p.panel,style)		
		SetGadgetLayout p.htmlview,1,1,1,1
'		p.Home
		p.buildtree
		Return p
	End Function

End Type

Type TSearchRequester Extends TRequester
	Field	findbox:TGadget,typebox:TGadget,pathbox:TGadget,pathbutton:TGadget

	Method Poll()
		Local	id,data,index
		id=EventID()
		data=EventData()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case ok
				Hide				
			Case cancel
				Hide
		End Select
	End Method

	Function Create:TSearchRequester(host:TCodePlay)
		Local	search:TSearchRequester
		search=New TSearchRequester
		search.initrequester(host,"Find In Files",400,256)

		CreateLabel("Find What",6,18,80,24,search.window)
		search.findbox=CreateTextField(88,14,180,20,search.window)

		CreateLabel("File Types",6,48,80,24,search.window)
		search.typebox=CreateTextField(88,44,180,20,search.window)

		CreateLabel("Search Path",6,78,80,24,search.window)
		search.pathbox=CreateTextField(88,74,180,20,search.window)

		Return search
	End Function
End Type

Type TProjectRequester Extends TRequester
	Field	projects:TProjects
	Field	listbox:TGadget,add:TGadget,remove:TGadget,props:TGadget

	Method Invoke(command,arg:Object=Null)
		Select command
		Case TOOLACTIVATE 
			Refresh
		End Select
	End Method

	Method Poll()
		Local	id,data,index
		id=EventID()
		data=EventData()
		Select EventSource()
			Case window
				If EventID()=EVENT_WINDOWCLOSE
					Hide
				EndIf
			Case add
				projects.AddProject
				Refresh
			Case remove
				projects.RemoveProject SelectedGadgetItem(listbox)
				Refresh
			Case ok
				Hide				
			Case cancel
				Hide
		End Select
	End Method

	Method Refresh()
		Local	node:TNode
		
		ClearGadgetItems listbox
		For node=EachIn projects.kids
			If TFolderNode(node)'node.argument
				AddGadgetItem listbox,node.name
			EndIf
		Next
	End Method
	
	Method Open(projnode:TProjects)
		projects=projnode
		Refresh
		Show
	End Method
	
	Function Create:TProjectRequester(host:TCodePlay)
		Local x,y
		Local	proj:TProjectRequester
		proj=New TProjectRequester
	
		proj.initrequester(host,"Project Manager",400,256)
		proj.listbox=CreateListBox( 8,8,248,184,proj.window )
		
		x=ClientWidth(proj.window)-136
		proj.add=CreateButton("Add Project",x,8,128,24,proj.window)
		proj.remove=CreateButton("Remove Project",x,40,128,24,proj.window)
		proj.props=CreateButton("Properties",x,72,128,24,proj.window)
		DisableGadget proj.props 
		Return proj
	End Function
End Type


Type TFolderNode Extends TNode
	Field	path$
	Field	scanned
	Field	owner:TNode

	Method Open(view=-1)
		If Not scanned
			ScanKids		'Path name,path
		EndIf
		Super.Open view
	End Method

	Method AddFileNode:TNode(file$)
		Local	n:TNode
		Local 	ext$
		
		If NodeFileTypes.find("|"+ExtractExt(file).toLower()+"|")<0 Return
		n=AddNode(StripDir(file))
		n.SetAction(owner,TOOLOPEN,file)
		ext=ExtractExt(file$).ToLower()
		n.sortname=ext+n.name
		Return n
	End Method

	Method AddFolderNode:TNode(path$)
		Local	n:TNode
		n=TFolderNode.Create(path)
		n.sortname=" "+n.name
		Append n
		Return n
	End Method

	Method Scan(o:TNode)
		Local	flist:TList
		Local	dir,f$,p$,t	
		owner=o
		flist=New TList
		dir=ReadDir(path)
		If dir
			Repeat
				f$=NextFile(dir)
				If f$="" Exit
				If f[..1]="." Continue
				p$=path+"/"+f
				Select FileType(p$)
				Case FILETYPE_FILE
					AddFileNode p$
				Case FILETYPE_DIR
					AddFolderNode p$
				End Select				
			Forever
			CloseDir dir
		EndIf
		SortKids
	End Method
	
	Method ScanKids()
		Local	f:TFolderNode		
		If scanned Return
		For f=EachIn kids
			f.Scan owner
		Next
		scanned=True
	End Method

	Function Create:TFolderNode(path$)
		Local	n:TFolderNode
'		print "create foldernode "+path
		n=New TFolderNode
		n.setname StripDir(path)
		n.path=path
		Return n
	End Function
End Type

Type TProjects Extends TNode
	Field	host:TCodePlay
	Field	addproj:TNode
	
	Method RemoveProject(index)
		Local	node:TNode
		If index<0 Or index>=kids.Count() Return
		node=TNode(kids.ValueAtIndex(index))
		If node node.Free
		Refresh
	End Method			
	
	Method AddProject()
		Local	path$,name$,stream:TStream
		path=RequestDir("Select the project folder")
		If Not path Return
		Add path,path
'		addproj.Detach
'		Append TFolderNode.Create(path)		
'		name=StripDir(path)		
'		If Not ScanPath(Self,name,path)	
'			If Confirm("No source files found, create "+name+".bmx?")
'				stream=WriteStream(path+"/"+name+".bmx")
'				If stream CloseStream stream
'				ScanPath(Self,name,path)
'			EndIf
'		EndIf
'		Append addproj
'		Refresh
	End Method

	Method Add(name$,path$)
		Local folder:TFolderNode
		addproj.Detach
		folder=TFolderNode.Create(path)
		folder.Scan Self
		Append folder
		Append addproj
		Refresh
	End Method

	Method Write(stream:TStream)
		Local	project:TFolderNode
		For project=EachIn kids
			stream.WriteLine "proj_node="+project.name+"|"+project.path'node.argument.ToString()
		Next
	End Method

	Method Invoke(command,argument:Object=Null)
		Select command
		Case TOOLNEW
			AddProject
		Case TOOLOPEN
			host.OpenSource String(argument)
		End Select
	End Method
			
	Function CreateProjects:TProjects(host:TCodePlay)
		Local	p:TProjects
		p=New TProjects
		p.SetName("Projects")
		p.host=host
		p.addproj=p.AddNode("Add Project")
		p.addproj.SetAction p,TOOLNEW
		Return p
	End Function
End Type

Type TByteBuffer Extends TStream
	Field	bytes:Byte[]
	Field	readpointer

	Method Read( buf:Byte Ptr,count )
		If count>readpointer count=readpointer
		If count=0 Return
		MemCopy buf,bytes,count
		readpointer:-count
		If readpointer MemMove bytes,Varptr bytes[count],readpointer
		Return count 
	End Method

	Method Write( buf:Byte Ptr,count )
		Local	n,m
		n=readpointer+count
		If n>bytes.length
			m=Max(bytes.length*1.5,n)
			bytes=bytes[..m]
		EndIf
		MemCopy Varptr bytes[readpointer],buf,count
		readpointer=n
		Return count
	End Method	
	
	Method LineAvail()
		Local	i
		For i=0 Until readpointer
			If bytes[i]=10 Return True
		Next
	End Method

	Method FlushBytes:Byte[]()
		Local res:Byte[]=bytes[..readpointer]
		readpointer=0
		Return res
	End Method
End Type

Type TObj
	Field	addr$,sync,refs
End Type

Type TVar Extends TNode

	Field	owner:TDebugTree
	Field	obj:Object

	Method Free()
		If obj owner.RemoveObj obj
		obj=Null
		Super.Free()
	End Method

	Method SetVarName(n$)
		Local	p
		name=n
' if object ref set addr$ field	
		If name.find("$=")=-1 And name.find(")=$")=-1
			p=name.find("=$")
			If p<>-1
				TDebugTree.RemoveObj obj
				obj=TDebugTree.AddObj(name[p+2..])
			EndIf
			p=name.find("=Null")
			If p<>-1
				FreeKids
				TDebugTree.RemoveObj obj
				obj=Null
			EndIf
		EndIf
	End Method
	
	Method AddVar(name$)
		Local	v:TVar
		v=New TVar
		v.setvarname name
		v.owner=owner
		Append v
	End Method
	
	Method SetValue(val:TVar)
		Local	v:TVar,w:TVar,i
' if this is a reference to same object refresh values	
		If obj And obj=val.obj
'			sync=val.sync
			If kids.IsEmpty()
				For v=EachIn val.kids
					AddVar v.name
				Next
			Else
				For v=EachIn val.kids
					If i<kids.count()
						w=TVar(kids.ValueAtIndex(i))
						If w w.SetVarName v.name
					Else
						AddVar v.name
					EndIf
					i:+1
				Next			
			EndIf
			Refresh
		EndIf	
' recurse so all references are updated
		If IsHidden() Return				'parent And parent.state=CLOSEDSTATE Return
		For v=EachIn kids
			v.SetValue val
		Next
	End Method
	
	Method Open(view=0)
		owner.sync:+1
		Super.Open view
		owner.SyncVars
	End Method
	
End Type

Type TScope Extends TVar
	Field	tree:TDebugTree
	Field	file$,line,column

	Method Invoke(command,argument:Object=Null)
		Select command
			Case TOOLACTIVATE
				tree.SelectScope Self,True
		End Select
	End Method
	
	Method SetScope(s:TScope)
		Local	v:TVar
		file=s.file
		line=s.line
		column=s.column
		s.obj=Self
		SetValue s
	End Method
	
	Method SetFile(debugtree:TDebugTree,f$)
		Local	p,q,r
		tree=debugtree
		p=Instr(f,"<")
		q=Instr(f,">")
		r=Instr(f,",")
		If p And q And r
			file=f[..p-1]
			line=Int(f[p..r-1])
			column=Int(f[r..q-1])
		EndIf
		obj=Self
	End Method
End Type

Type TDebugTree Extends TVar
	Global	sync
	Global	objlist:TList
	Field	host:TCodePlay
	Field	instack:TList
	Field	inscope:TScope
	Field	invar:TVar
	Field	infile$
	Field	inexception$
	Field	firststop
	Field	cancontinue
		
	Method Reset()
		host.SetMode host.DEBUGMODE
		SetStack New TList
		objlist=New TList	
		instack=Null
		inscope=Null
		invar=Null
		infile=""
		inexception=""
		sync=0
		firststop=True
		cancontinue=False
	End Method

	Function AddObj:TObj(addr$)
		Local	o:TObj
		For o=EachIn objlist
			If o.addr=addr 
				o.refs:+1
				Return o
			EndIf
		Next
		o=New TObj
		o.addr=addr
		o.refs=1
		objlist.addlast o
		Return o
	End Function

	Function FindObj:TObj(addr$)
		Local	o:TObj
		For o=EachIn objlist
			If o.addr=addr Return o
		Next
	End Function
	
	Function RemoveObj(obj:Object)		':TObj
		Local	o:TObj
		o=TObj(obj)
		If Not o Return
		o.refs:-1
		If o.refs=0 
			objlist.Remove o
		EndIf
	End Function

	Method SyncVars()
		Local	o:TObj
		For o=EachIn objlist
			If o.sync<sync 
				o.sync=sync
				host.output.WritePipe "d"+o.addr
			EndIf
		Next		
	End Method
			
	Method SetStack(list:TList)
		Local	scope:TScope
		Local	openscope:TScope
		Local	s:TScope
		Local	count,i

		count=kids.count()			'root.varlist.count()
		For scope=EachIn list
			If i>=count
				Append scope		'root.Append scope
				s=scope
			Else
				s=TScope(kids.ValueAtIndex(i))
' simon was here				
				If s.name=scope.name
					s.SetScope scope
					scope.Free
				Else
					While kids.count()>i
						s=TScope(kids.ValueAtIndex(i))
						s.free
					Wend
					Append scope
					s=scope
					count=i+1
				EndIf
				
			EndIf
			If firststop
				If host.IsSourceOpen(s.file) openscope=s
			Else
				openscope=s
			EndIf
			i:+1
		Next
		While kids.count()>i
			scope=TScope(kids.ValueAtIndex(i))
			scope.free
		Wend 
		If list.isempty() Return
		If Not openscope openscope=TScope(list.First())
		If openscope SelectScope openscope,True
		Refresh
		firststop=False
	End Method

	Method SelectScope(scope:TScope,open)
		If Not scope Return		
		If scope.file host.DebugSource scope.file,scope.line,scope.column
		scope.Open
'		If open
'			SelectTreeViewNode scope.node
'			scope.open
'		EndIf
	End Method

	Method ProcessError$(line$)
		Local	p
				
		While line[..1]=">" 
			line=line[1..]
		Wend
		If Not line Return

		If line[..2]<>"~~>" Return line

		line=line[2..]

		If invar
			If line="}"
				SetValue invar		'root
				invar.Free
				invar=Null
			Else
'				If Not invar.name
'					invar.name=line
'				Else
					invar.AddVar line
'				EndIf
			EndIf
			Return
		EndIf
		
		If instack 			
			If line="}" 
				sync:+1
				SetStack instack
				instack=Null
				inscope=Null
				SyncVars
				If inexception
					Notify inexception
					inexception=""
				EndIf
				Return
			EndIf
			
			If infile
				If line="Local <local>"
				Else
					inscope=New TScope
'					Print "inscope.line="+line
					inscope.name=line
					inscope.owner=Self
					instack.AddLast inscope
				EndIf
				If inscope inscope.setfile Self,infile
				infile=""
				Return
			EndIf

			If Instr(line,"@")=1 And Instr(line,"<")
				infile=line[1..]
			Else
				If inscope inscope.AddVar line
			EndIf

			Return
		EndIf

		If line[..20]="Unhandled Exception:"
			inexception=line
			host.output.WritePipe "t"
			cancontinue=False
			Return
		EndIf

		If line="StackTrace{" 
			instack=New TList
			Return
		EndIf

		If line="Debug:" Or line="DebugStop:"
			host.output.WritePipe "t"
			cancontinue=True
			Return
		EndIf					
		
		If line[..11]="ObjectDump@"
			p=line.find("{")
			If p=-1 Return line
			line=line[11..p]
			invar=New TVar
'			invar.obj=AddObj(line)
			invar.obj=FindObj(line)	'simon come here
			invar.owner=Self
			Return
		EndIf
		
	End Method

	Function CreateDebugTree:TDebugTree(host:TCodePlay)
		Local	d:TDebugTree
		objlist=New TList
		d=New TDebugTree
		d.owner=d
		d.SetName "Debug"
		d.host=host
		d.Open
		Return d		
	End Function
End Type

Type TNodeView
	Field	owner:TNavBar
	Field	root:TNode
	Field	treeview:TGadget
	Field	index
	
	Method NewView()
		Local	n:TNode,hnode:TGadget
		hnode=SelectedTreeViewNode(treeview)
		n=root.Find(hnode,index)
		If n And n.parent owner.AddView n
	End Method

	Method OnEvent()
		Local	n:TNode
		n=root.Find(TGadget(EventExtra()),index)
		If Not n Return
		Select EventID()
			Case EVENT_GADGETSELECT
				n.invoke(TOOLSELECT)				
			Case EVENT_GADGETACTION
				n.invoke(TOOLACTIVATE)				
			Case EVENT_GADGETMENU
				n.invoke(TOOLMENU,Self)
			Case EVENT_GADGETOPEN
				n.open index
			Case EVENT_GADGETCLOSE
				n.close index
		End Select
	End Method
End Type

Type TNavBar Extends TEventHandler
	Field	host:TCodePlay
	Field	tabber:TGadget
	Field	viewlist:TList=New TList
	Field	selected:TNodeView
	Field	navmenu:TGadget
	
	Method SelectedView()
		If selected Return selected.index
	End Method
		
	Method SelectView(index)
		Local	n:TNodeView
		If index>=viewlist.count() Return
		n=TNodeView(viewlist.ValueAtIndex(index))
		If Not n Print "selectview failed";Return
		If n<>selected
			If selected HideGadget selected.treeview
			selected=n
		EndIf
		ShowGadget n.treeview
		SelectGadgetItem tabber,index
	End Method
	
	Method AddView(node:TNode)
		Local	n:TNodeView
		Local	index,root:TGadget
		For n=EachIn viewlist
			If n.root=node SelectView n.index;Return
		Next
		n=New TNodeView
		n.owner=Self
		n.root=node
		n.treeview=CreateTreeView(0,0,ClientWidth(tabber),ClientHeight(tabber),tabber)
		host.options.navstyle.Apply n.treeview
		SetGadgetLayout n.treeview,1,1,1,1
		HideGadget n.treeview

		viewlist.AddLast n		
		n.index=viewlist.Count()

		AddGadgetItem tabber,node.name
		root=TreeViewRoot(n.treeview)
		node.setnode root,n.index
		SelectView n.index
		Return n.index
	End Method

	Method OnEvent()
		If EventSource()=tabber
			SelectView SelectedGadgetItem(tabber)				
		End If
		If selected And EventSource()=selected.treeview
			selected.OnEvent
		EndIf
	End Method

	Method Refresh()
		Local	view:TNodeView
		For view=EachIn viewlist
			host.options.navstyle.Apply view.treeview
		Next
	End Method

	Method Invoke(command,argument:Object=Null)
		If command=TOOLREFRESH Refresh()		
		If command=TOOLNEWVIEW And selected selected.NewView
	End Method

	Function CreateNavMenu:TGadget()
		Local	edit:TGadget
		edit=CreateMenu("&Nav",0,Null)
		CreateMenu "&New View",MENUNEWVIEW,edit
		Return edit
	End Function

	Function Create:TNavBar(host:TCodePlay)	',root:TNode)
		Local	n:TNavBar
		n=New TNavBar
		n.host=host	
		n.tabber=CreateTabber(0,0,1,1,host.client)
'		n.AddView root
		n.navmenu=CreateNavMenu()
		Return n		
	End Function

End Type

Comments

skidracer2006
Oops, gets cut off.

part 2:

Type TOutputPanel Extends TToolPanel	'used build and run

	Field	host:TCodePlay
	Field	output:TGadget
	Field	process:TProcess
	Field	user$,cmdline$,err$,post$
	Field	errbuffer:TByteBuffer
	Field	outputmenu:TGadget

	Method Clear()
		If Not output Open()
		SetGadgetText output,""
	End Method
	
	Method Write(mess$)
		If Not output Open()
		AddTextAreaText output,mess
	End Method

	Method Execute(cmd$,mess$="",exe$="",home=True)
		If Not output Open()
		If Not mess$ mess$=cmd$
		err$=""
		post$=exe
		host.SelectPanel Self
		host.debugtree.Reset
		If process And ProcessStatus(process)
			Delay 500
			If ProcessStatus(process)
				Notify "Current process still busy "+cmdline 
				Return
			EndIf
		EndIf
		cmd=cmd.Trim()
		process=CreateProcess(cmd$,HIDECONSOLE)
		If Not process Notify "Process Failure with "+cmd;Return
		If Not process.status() Notify "Process Failed to start "+cmd;Return		
		cmdline=cmd
		If home Clear
		Write mess$+"~n"
		errbuffer=New TByteBuffer
		host.RefreshToolbar	
	End Method

	Method WritePipe(l$)
		Local	pipe:TPipeStream
		If Not process Return		
		pipe=process.pipe
		pipe.WriteLine(l$)
	End Method

	Method Go()
		WritePipe "r"
	End Method
	
	Method StepOver()
		WritePipe "s"
	End Method
	
	Method StepIn()
		WritePipe "e"
	End Method

	Method StepOut()
		WritePipe "l"
	End Method
	
	Method Stop()
		If Not process Return		
		process.Terminate
		FlushPipes process.pipe,process.err		
		process.Close
		process=Null
		Write "~nProcess terminated~n"
		host.DebugExit
		Close
	End Method
	
	Method Wait()
		While process And process.status()
			PollSystem
		Wend
	End Method
	
	Method Invoke(command,argument:Object=Null)
		Select command
			Case TOOLSHOW 
				host.SetTitle
				If output ActivateGadget output	
			Case TOOLCLOSE
				host.RemovePanel Self
				output=Null
			Case TOOLCUT
				GadgetCut output
			Case TOOLCOPY
				GadgetCopy output
			Case TOOLPASTE
				GadgetPaste output
			Case TOOLSELECTALL 
				If output SelectTextAreaText output
			Case TOOLREFRESH
				host.options.outputstyle.apply output
		End Select
	End Method
	
	Method Close()
		host.SelectPanel host.activepanel
	End Method
	
	Method Escape()
		Stop
		Close
	End Method
	
	Function outputfilter(event:TEvent,context:Object)
		Local out:TOutputPanel=TOutputPanel(context)
		If Not out Return
		Select event.id
			Case EVENT_KEYDOWN
				If event.data=27
					out.Escape()
					Return 0
				EndIf
			Case EVENT_KEYCHAR
'				Print "output_keychar "+event.data
				out.writechar(event.data)
		End Select
		Return 1
	End Function
	
	Method OnEvent()
		If EventSource()=output
			If EventID()=EVENT_GADGETMENU
				PopupWindowMenu host.window,outputmenu
			EndIf
		EndIf
' Case EVENT_TIMERTICK
		If Not process Return		

		ReadPipes process.pipe,process.err

		Local status=process.status()
		If status=0
			process.terminate
			FlushPipes process.pipe,process.err
			process.close
			process=Null
			Write "~nProcess complete~n"
			host.DebugExit
			host.SelectPanel Self

			If err 
				host.ParseError err
			Else
				If post$
					Local menuaction=Int(post)
					If menuaction
						host.OnMenu menuaction
					Else				
'						Execute post$,"","",False,0
					EndIf
				Else
					If host.options.hideoutput Close
				EndIf
			EndIf
			Return
		EndIf	
	End Method
		
	Method FlushPipes(pipe:TPipeStream,errpipe:TPipeStream)
		ReadPipes(pipe,errpipe)
		Local bytes:Byte[]=errbuffer.flushbytes()
		If bytes
			Local line$=String.FromBytes(bytes,Len bytes)
			line=line.Replace$(Chr(13),"")
			If line<>">" Write line
		EndIf
	End Method
		
	Method ReadPipes(pipe:TPipeStream,errpipe:TPipeStream)
		Local	status
		Local	bytes:Byte[],line$

		bytes=pipe.ReadPipe()
		If bytes
			line$=String.FromBytes(bytes,Len bytes)
			line=line.Replace$(Chr(13),"")
			Write line
		EndIf
				
'		While buffer.LineAvail()
'			line$=buffer.ReadLine()
'			line=host.debugtree.ProcessError(line)
'			If line 
'				Write line+"~n"
'				err:+line+"~n"
'			EndIf
'		Wend

		bytes=errpipe.ReadPipe()
		If bytes errbuffer.WriteBytes bytes,Len bytes
		
'		If bytes Write String.FromBytes(bytes,bytes.length)
		While errbuffer.LineAvail()
			line$=errbuffer.ReadLine()
			line=host.debugtree.ProcessError(line)
			If line 
				Write line+"~n"
				err:+line+"~n"
			EndIf
		Wend
	End Method
	
	Method WriteChar(char)
		Local	pipe:TPipeStream
		If Not process Return		
		pipe=process.pipe
		If char=3			'CTRL-C
			Stop()
		EndIf
		If char=13			'ENTER
'			Write Chr(10)
			pipe.WriteLine user$
			user$=""
		EndIf
		If char=8			'DELETE
			If Len user
'				Local pos=TextAreaLen(output)
'				If pos SetTextAreaText output,"",pos-1,1,TEXTAREA_CHARS
				user=user[..Len user-1]
			EndIf
		EndIf
		If char>31
'			Write Chr(char)
			user:+Chr(char)
		EndIf
	End Method
		
	Method Open()
		If output codeplay.SelectPanel Self;Return
		codeplay.addpanel(Self)		
		output=CreateTextArea(0,0,ClientWidth(panel),ClientHeight(panel),panel,TEXTAREA_WORDWRAP)
		SetGadgetLayout output,1,1,1,1
		SetGadgetFilter output,outputfilter,Self
		SetGadgetText output," "	'simon was here		
		host.options.outputstyle.apply output
	End Method

	Function CreateOutputMenu:TGadget()
		Local	edit:TGadget
		edit=CreateMenu("Edit",0,Null)
		CreateMenu "Cut",MENUCUT,edit
		CreateMenu "Copy",MENUCOPY,edit
		CreateMenu "Paste",MENUPASTE,edit
		CreateMenu "",0,edit
		CreateMenu "Stop",MENUSTOP,edit
		Return edit
	End Function

	Function Create:TOutputPanel(host:TCodePlay)
		Local	o:TOutputPanel
		o=New TOutputPanel
		o.host=host		
		o.name="Output"
		o.outputmenu=CreateOutputMenu()
'		o.Open
		Return o
	End Function

End Type

Type TCodeNode Extends TNode
	Field	owner:TOpenCode
	Field	pos,count

	Method Invoke(command,argument:Object=Null)
		Select command
			Case TOOLACTIVATE
				owner.ShowPos(pos)
		End Select
	End Method

	Method Sync(snap:TNode)
		Local	n:TCodeNode		
		If snap.name<>name SetName(snap.name)
		n=TCodeNode(snap)
		If n pos=n.pos;count=n.count
		Super.Sync(snap)
	End Method
	
	Method SetName(n$)
		Local	p
		p=n.find("'")
		If p<>-1 n=n[..p]
		name=n.Trim()
	End Method
		
	Method AddCodeNode:TCodeNode(n$,p0,p1)
		Local	c:TCodeNode
'		print "AddCodeNode "+n$
		c=New TCodeNode
		c.owner=owner
		c.setname n$
		c.pos=p0
		c.count=p1-p0
		Append c
		Return c
	End Method
End Type

Type TDiff
	Field	pos,count,del$,add$,pos0,count0,pos1
End Type

Type TOpenCode Extends TToolPanel

	Field	host:TCodePlay
	Field	textarea:TGadget
	Field	dirty=True
	Field	filesrc$,cleansrc$,cleansrcl$
	Field	current:TDiff
	Field	undolist:TList=New TList
	Field	redolist:TList=New TList
	Field	helpcmd$,helpstring$
	Field	seek$
	Field	cursorpos,cursorlen,cursorline
	Field	oldpos,oldlen
	Field	isbmx,isc,iscpp,ishtml
	Field	deferpos
	Field	editmenu:TGadget
	Field	codenode:TNode
	Field	dirtynode,uc

	Function IsNotAlpha(c)
		If c<48 Return True
		If c>=58 And c<65 Return True
		If c>=91 And c<95 Return True
		If c>=96 And c<97 Return True
		If c>=123 Return True
	End Function
	
	Function WordAtPos$(a$,p)
		Local	c,q,r,n
	' string literal
		q=a.findlast(EOL$,a.length-p)
		If q=-1 q=0
		For q=q To p-1
			If a$[q]=34 n=Not n;r=q
		Next
		If n	
			q=a.Find(Chr(34),r+1)+1
			If q=0 q=a.length
			Return a[r..q]
		EndIf
	' alphanumeric
		For p=p To 0 Step -1
			If IsNotAlpha(a$[p]) Continue
			Exit
		Next
		For q=p-1 To 0 Step -1
			If IsNotAlpha(a$[q]) Exit
		Next
		For r=p To a.length-1
			If IsNotAlpha(a$[r]) Exit
		Next
		Return a$[q+1..r]
	End Function
	
	Function FirstDiff(s0$,s1$)
		Local	n,i
		n=Min(s0.length,s1.length)
		For i=0 Until n
			If s0[i]<>s1[i] Return i
		Next
		Return n		
	End Function
	
	Function LastDiff(s0$,s1$)
		Local	n,i,j
		n=Min(s0.length,s1.length)
		i=s0.length-1
		j=s1.length-1
		While n>0
			If s0[i]<>s1[j] Exit
			i:-1;j:-1;n:-1
		Wend
		Return i+1
	End Function
		
	Method GetNode:TNode()
		Local	root:TCodeNode,n:TCodeNode
		Local	src$,line,col
		Local	p,p1,r,t,m,f,l,e

'		if codenode return codenode		
		n=New TCodeNode
		n.name=StripDir(path)
		n.owner=Self
		n.count=src.length
		root=n
'update rem,type,method,function,label pointers
		src=cleansrcl
		p1=src.length
		p=-1;r=-1;t=-1;m=-1;f=-1;l=-1
		While p<p1			'src.length
			While r<=p
				r=FindToken("rem",src,r+1)
			Wend
			While t<=p
				t=FindToken("type",src,t+1)
			Wend
			While m<=p
				m=FindToken("method",src,m+1)
			Wend
			While f<=p
				f=FindToken("function",src,f+1)
			Wend
			While l<=p
				l=FindLabel(src,l+1)
			Wend
			If r<t And r<m And r<f And r<l
				p=FindEndToken("rem",src,r+1,True)
				Continue
			EndIf
			p=Min(t,Min(m,Min(f,l)))
			If p=src.length Exit		
			While (n And n.parent And p>n.pos+n.count) 
				n=TCodeNode(n.parent)
			Wend
			If t<m And t<f And t<l
				e=src.find(EOL,t)
				n=n.AddCodeNode(cleansrc[t..e],t,FindEndToken("type",src,t,True))
				p=t+1
				Continue
			EndIf
			If m<f And m<l
				e=src.find(EOL,m)
				n.AddCodeNode(cleansrc[m..e],m,e)
				p=m+1
				Continue
			EndIf
			If f<l
				e=src.find(EOL,f)
				n.AddCodeNode(cleansrc[f..e],f,e)
				p=f+1
				Continue		
			Else
				e=src.find(EOL,l)
				n.AddCodeNode(cleansrc[l..e],l,e)
				p=l+1
				Continue				
			EndIf
		Wend
		If codenode
			codenode.Sync(root)	
			root.Free
		Else
			codenode=root
		EndIf
		Return codenode
	End Method

	Method ShowPos(pos)
		host.SelectPanel Self
		SelectTextAreaText textarea,TextAreaLine(textarea,pos),0,TEXTAREA_LINES
		SelectTextAreaText textarea,TextAreaLine(textarea,pos),1,TEXTAREA_LINES
		UpdateCursor
		ActivateGadget textarea
	End Method

	Method Debug(line,column)
		SelectTextAreaText textarea,line-1,0,TEXTAREA_LINES
		SelectTextAreaText textarea,line-1,1,TEXTAREA_LINES
	End Method

	Method Edit()
		SelectTextAreaText textarea,cursorpos,0,TEXTAREA_CHARS
		ActivateGadget textarea
		UpdateStatus
	End Method
	
	Method UpdateStatus()
		Local	c
		c=cursorpos+cursorlen
		If cursorline c=c-TextAreaChar(textarea,cursorline-1)
		host.SetStatus helpstring+"~t~t"+"Line: "+(cursorline)+" Char: "+(c+1)+"     "
	End Method
	
	Method UpdateCursor()
		Local	l	
		oldpos=cursorpos
		oldlen=cursorlen
		cursorpos=TextAreaCursor(textarea,TEXTAREA_CHARS)
		cursorlen=TextAreaSelLen(textarea,TEXTAREA_CHARS)
		If cursorpos<>oldpos Or cursorlen<>oldlen
			l=TextAreaLine(textarea,cursorpos)+1
			If l<>cursorline And dirtynode
				GetNode().Refresh
				dirtynode=False
				If deferpos UpdateCode	'SetCode cleansrc
			EndIf
			cursorline=l
			UpdateStatus()
			PollSystem
		EndIf
	End Method

' tdiff - pos del$ add$

	Method CalcDiff:TDiff(src$)
		Local	d:TDiff

		If src.length<>cleansrc.length
			d=New TDiff
			d.pos0=cursorpos
			d.count0=cursorlen
			d.pos=oldpos
			d.count=oldlen
			If cursorlen And oldlen							'block modified
				d.del=cleansrc[oldpos..oldpos+oldlen]
				d.add=src[oldpos..cursorpos+cursorlen]
				d.pos1=oldpos
			Else
				If cursorpos<=oldpos And cursorlen<=oldlen	'backspace
					d.del=cleansrc[cursorpos..cursorpos+cleansrc.length-src.length]
					d.pos1=cursorpos
				Else										'insert
					d.del=cleansrc[oldpos..oldpos+oldlen]
					d.add=src[oldpos..cursorpos+cursorlen]
					d.pos1=oldpos
				EndIf
			EndIf
			Return d		
		EndIf		
		If cursorpos>oldpos									'overwrite
			d=New TDiff
			d.pos0=cursorpos
			d.count0=cursorlen
			d.pos=oldpos
			d.count=oldlen
			d.del=cleansrc[oldpos..cursorpos]
			d.add=src[oldpos..cursorpos]
			d.pos1=oldpos
			Return d		
		EndIf		
	End Method

	Method UpdateCode(makeundo=True)
		Local	cpos,src$
		Local	d:TDiff

		src=TextAreaText(textarea)		
		d=CalcDiff(src)
		If d		
			If makeundo
				undolist.AddLast d
				redolist.Clear
			EndIf
			SetCode src,d
			dirtynode=True
		Else
			If deferpos SetCode src
		EndIf
	End Method
	
	Method Undo()
		Local	d:TDiff
		If undolist.isempty() Return
		d=TDiff(undolist.RemoveLast())
		redolist.AddLast d
		SetTextAreaText textarea,d.del,d.pos1,d.add.length
		SelectTextAreaText(textarea,d.pos,d.count)
		SetCode TextAreaText(textarea),d
		UpdateCursor
	End Method

	Method Redo()
		Local	d:TDiff
		If redolist.isempty() Return
		d=TDiff(redolist.RemoveLast())
		undolist.AddLast d
		SetTextAreaText textarea,d.add,d.pos,d.del.length
		SelectTextAreaText(textarea,d.pos0,d.count0)
		UpdateCursor
		SetCode TextAreaText(textarea),d
	End Method

	Method Refresh()
		Local	rgb:TColor
		Local	src$
		SetTextAreaTabs textarea,host.options.tabsize
		SetTextAreaFont textarea,host.options.editfont
		rgb=host.options.editcolor
		SetTextAreaColor textarea,rgb.red,rgb.green,rgb.blue,True
		rgb=host.options.styles[0].color
		SetTextAreaColor textarea,rgb.red,rgb.green,rgb.blue,False
		src=cleansrc
		cleansrc=""
		cleansrcl=""
		cursorpos=0
		SetCode(src)
	End Method

	Function IsntAlphaNumeric(c)		'lowercase test only
		If c<47 Return True
		If c>=58 And c<95 Return True
		If c=96 Return True
		If c>=123 Return True
	End Function
	
	Function IsntAlphaNumericOrQuote(c)		'lowercase test only
		If c=34 Return False
		If c<47 Return True
		If c>=58 And c<95 Return True
		If c=96 Return True
		If c>=123 Return True
	End Function

	Function IsCode(src$,p)
		Local	l,q,n
		l=src.FindLast(EOL$,src.length-p)
		If l=-1 l=0
		q=src.Find("'",l)
		If q<>-1 And q<p Return
		q=l
		While q<p
			q=src.Find(QUOTES$,q)+1
			If q=0 Exit
			If q<=p n:+1
		Wend
		If n&1 Return
		Return True		
	End Function

	Function FindLabel(src$,pos)
		Local	p,q,c
		While pos>=0
			p=src.Find("#",pos)
			If p=-1 Exit
			q=p
			While q>0
				q:-1
				c=src[q]
				If c=13 Return p
				If c=10 Return p
				If c=32 Or c=9 Continue
				Exit
			Wend
			If q=0 Return p
			pos=p+1
		Wend
		Return src.length	
	End Function
	
	Function FindToken(token$,src$,pos)	'lowercase src only!
		Local	p,c,n
		n=token.length
		While pos>=0
			p=src.Find(token,pos)
			If p=-1 Exit
			c=10 If p>0 c=src[p-1]
			If isntalphanumeric(c) 
				If p+n<src.length c=src[p+n]
				If isntalphanumeric(c) 
					If iscode(src,p)
						If p<4 Or src[p-4..p]<>"end " Return p
					EndIf
				EndIf
			EndIf
			pos=p+1
		Wend
		Return src.length
	End Function

	Function FindEndToken(token$,src$,pos,returnlast=False)	'if true returns first character after endtoken
		Local	p,q,e$,n
		
		p=pos
		e$="end"+token
		n=e.length
		While p<src.length
			p=src.Find(e$,p)
			If p=-1 Exit
			If p+n=src.length Or isntalphanumeric(src[p+n])
				If iscode(src,p)
					If p=0 Or isntalphanumeric(src[p-1]) Exit
				EndIf
			EndIf
			p=p+n
		Wend
		If p=-1 p=src.length Else If returnlast p:+n
		q=pos
		e$="end "+token
		n=e.length
		While q<src.length
			q=src.Find(e$,q)
			If q=-1 Exit
			If q+n=src.length Or isntalphanumeric(src[q+n])
				If iscode(src,q)
					If q=0 Or isntalphanumeric(src[q-1]) Exit
				EndIf
			EndIf
			q=q+n
		Wend
		If q=-1 q=src.length Else If returnlast q:+n
		Return Min(p,q)
	End Function

	Function IsFirstCharOnLine(src$,pos)
		Local	i,c
		For i=1 To pos
			c=src[pos-i]
			If c=10 Or c=13 Return True
			If c>32 Return False
		Next
		Return True
	End Function

' rem and endrem must be first nonwhitespace on line - following funcs are for lowercase src only

	Function FindRem(src$,pos)
		While pos<src.length
			pos=FindToken("rem",src,pos)
			If pos=src.length Exit
			If IsFirstCharOnLine(src,pos) Return pos
			pos:+1
		Wend
		Return pos
	End Function

	Function FindEndRem(src$,pos,returnlast=False)
		Local	i,c		
		While pos<src.length
			pos=FindEndToken("rem",src,pos)
			If pos=src.length Exit
			If IsFirstCharOnLine(src,pos)
				If returnlast 
					If src[pos+5]=Asc("e") Or src[pos+5]=Asc("E") pos:+1
					pos:+6
				EndIf
				Return pos
			EndIf
			pos:+1
		Wend
		Return src.length
	End Function

	Function FindPrevRem(src$,pos)	'lowercase src only!
		Local	p,c
		While pos>0
			If pos>src.length Exit
			p=src.FindLast("rem",src.length-pos)
			If p=-1 Exit						
			If isntalphanumeric(src[p+3]) And IsFirstCharOnLine(src,p) Return p			
			pos=p-1
		Wend
		Return -1
	End Function

	Method WasRemmed(pos,src$)
		Local	s$,p
		s$=cleansrcl
		p=src.length-s.length
		If p<0 pos:-p		
		p=FindPrevRem(s$,pos+3)
		If p=-1 Return
		p=FindEndRem(s$,p)
		If pos<p Return True
	End Method

	Method CheckDirty(src$)
		Local	bool
		bool=True
		If src=filesrc And undolist.isempty() bool=False
		SetDirty bool
	End Method

	Method SetCode(src$,diff:TDiff=Null)
		Local	i,p,p1,q,r,a,t$,h$,lsrc$,r0,r1,cpos,autocap
		Local	style:TTextStyle[4],s:TTextStyle

' update dirty flag	
		CheckDirty src
		If src=cleansrc And Not deferpos And Not diff Return	
		If Not isbmx Or Not host.quickhelp Or Not host.options.syntaxhighlight
			cleansrc=src
			cleansrcl=src.ToLower()
			Return
		EndIf
' doit
		autocap=host.options.autocapitalize
		lsrc=src.ToLower()

		cpos=TextAreaCursor(textarea,TEXTAREA_CHARS)
		LockTextArea textarea
		style=host.options.styles
' calculate highlight region
		If deferpos
			p=deferpos
			p1=p
			deferpos=0
		Else
			If diff
				p=diff.pos
				p1=p+diff.add.length
			Else
				p=firstdiff(src,cleansrc)
				p1=lastdiff(src,cleansrc)
			EndIf
			q=src.length-cleansrc.length
			If p1-p<q p1=p+q
			If p1<p p1=p
		EndIf
' round region to line breaks
'		Print "p="+p+" p1="+p1
		If p>0 p:-1
		If p>src.length p=src.length
		p=src.findlast(EOL,src.length-p)+1
		p1=src.find(EOL,p1)+1
		If p1=0 p1=Len src
' if endrem between p0,p1 and next rem after p1 move p1 forwards
		r1=FindEndRem(lsrc,p)
		If r1<p1 And wasremmed(r1+6,lsrc)
			r0=FindRem(lsrc,r1+6)
			If r0>p1 p1=r0
		EndIf
' if rem between p0,p1 and matching endrem after p1 move p1 forewards 
		r0=FindPrevRem(lsrc,p1)
		If r0>=p And r0+3<>cpos	'defer fix
			r1=FindEndRem(lsrc,r0,True)
			If r1>p1 p1=r1
		EndIf
' if rem before p0 and matching endrem after p0 highlight to endrem and move p0 forwards
		r0=FindPrevRem(lsrc,p)
		If r0<>-1 And r0<p
			r1=FindEndRem(lsrc,r0,True)
			If r1>p
				s=style[COMMENT]
				If r1>p s.Format(textarea,p,r1-p)
				If autocap And r1<src.length
					If lsrc[r1-6..r1]="endrem" And src[r1-6..r1]<>"EndRem" SetTextAreaText textarea,"EndRem",r1-6,6
					If lsrc[r1-7..r1]="end rem" And src[r1-7..r1]<>"End Rem" SetTextAreaText textarea,"End Rem",r1-7,7
				EndIf
				p=r1
			EndIf
		EndIf	
' if was remmed and now isn't move p1 down to nearest rem or endrem
		If WasRemmed(p,lsrc)
			r0=FindRem(lsrc,p)
			r1=FindEndRem(lsrc,r0,True)
			p1=Max(p1,Min(r0,r1))	
		EndIf
' highlight code
		s=style[NORMAL]
		If p1>p s.format(textarea,p,p1-p)
		While p<p1
			host.UpdateProgress("Highlighting Code",(p*100)/p1)
			a=src[p]
' quoted strings
			If a=34
				q=p1
				r=src.find(Chr(34),p+1)
				If r>-1 And r<q q=r+1
				r=src.find(EOL,p+1)
				If r>-1 And r<q q=r
				s=style[QUOTED]
				s.format(textarea,p,q-p)
				p=q
				Continue
			EndIf
' single line comments
			If a=39
				q=p1
				r=src.find(EOL,p+1)
				If r>-1 And r<q q=r
				s=style[COMMENT]
				s.format(textarea,p,q-p)
				p=q
				Continue				
			EndIf
' tokens
			If (a>=65 And a<91) Or (a>=97 And a<123) Or (a=95)
				q=p+1
				While q<p1
					a=src[q]
					If a<46 Exit
					If a=47 Exit
					If a>=58 And a<65 Exit
					If a>=91 And a<95 Exit
					If a=96 Exit
					If a>122 Exit
					q:+1
				Wend
				t$=src[p..q]
				h$=host.quickhelp.token(t$)
				If h$
					If h$<>t$ And autocap
						If q<>cpos
							SetTextAreaText textarea,h$,p,Len h
						Else
							deferpos=q
						EndIf
					EndIf
					s=style[KEYWORD]
					If h$="Rem" And IsFirstCharOnLine(lsrc,p)	' Not (p>4 And lsrc[p-4..p]="end ")
						If q<>cpos
							q=FindEndRem(lsrc,p,True)
							s=style[COMMENT]
						Else
							deferpos=q
						EndIf						
					EndIf
					s.format(textarea,p,q-p)
				EndIf
				p=q
				Continue
			EndIf
			p:+1
		Wend
		UnlockTextArea textarea
		cleansrc=src
		cleansrcl=lsrc
'		CheckDirty src	simon was here
	End Method

	Method AutoIndent()
		Local	t$,p,q,c,n
		c=TextAreaCursor(textarea,TEXTAREA_CHARS)
		n=TextAreaSelLen(textarea,TEXTAREA_CHARS)
		If c 
			p=cleansrc.FindLast(EOL$,cleansrc.length-(c-1))+1
			q=p
			While cleansrc[q]=9
				q:+1
			Wend
			If q>c q=c
		EndIf
		SetTextAreaText textarea,EOL$+cleansrc[p..q],c,n
		SelectTextAreaText textarea,c+1+q-p,0			
		UpdateCursor
		UpdateCode
	End Method
	
	Method IndentCode()
		Local	cpos,p0,p1,i,a$
' blockindent
		p0=TextAreaCursor(textarea,TEXTAREA_LINES)
		p1=TextAreaSelLen(textarea,TEXTAREA_LINES)
		For i=0 Until p1
			a$="~t"+TextAreaText(textarea,p0+i,1,TEXTAREA_LINES)
			SetTextAreaText textarea,a$,p0+i,1,TEXTAREA_LINES
		Next
		SelectTextAreaText textarea,p0,p1,TEXTAREA_LINES
		UpdateCursor
		UpdateCode
	End Method

	Method OutdentCode()
		Local	cpos,p0,p1,i,a$,modified
' blockoutdent
		p0=TextAreaCursor(textarea,TEXTAREA_LINES)
		p1=TextAreaSelLen(textarea,TEXTAREA_LINES)
		For i=0 Until p1
			a$=TextAreaText(textarea,p0+i,1,TEXTAREA_LINES)
			If a[0]=9 a$=a$[1..];modified=True
			SetTextAreaText textarea,a$,p0+i,1,TEXTAREA_LINES
		Next
		If Not modified
			For i=0 Until p1
				a$=TextAreaText(textarea,p0+i,1,TEXTAREA_LINES)
				If a[0]=32 a$=a$[1..]
				SetTextAreaText textarea,a$,p0+i,1,TEXTAREA_LINES
			Next	
		EndIf
		SelectTextAreaText textarea,p0,p1,TEXTAREA_LINES
		UpdateCursor
		UpdateCode
	End Method

	Function FilterKey(event:TEvent,context:Object)
		Local	this:TOpenCode
		Local	id,key,mods
'		If event.id<>EVENT_KEYCHAR Return 1
		id=event.id
		key=event.data
		mods=event.mods
		this=TOpenCode(context)
?MacOS
		If key=25 And mods=1 key=9
?
		If id=EVENT_KEYCHAR And this And key=9 And TextAreaSelLen( this.textarea,TEXTAREA_CHARS )
			Select mods
				Case 0
					this.IndentCode
				Case 1
					this.OutdentCode
			End Select
			Return 0
		EndIf

		If id=EVENT_KEYDOWN And this And key=13 And this.host.options.autoindent 
			this.AutoIndent 
			Return 0
		EndIf
		
		Return 1
	End Function

	Method OnEvent()
 		Select EventSource()
			Case textarea 
				Select EventID() 
					Case EVENT_GADGETMENU
						PopupWindowMenu host.window,editmenu
					Case EVENT_GADGETACTION
						UpdateCode
					Case EVENT_GADGETSELECT
						UpdateCursor
				End Select
		End Select
	End Method
			
	Method SetDirty( bool )
		If dirty=bool Return
		dirty=bool
		name=StripDir(path)
		If (dirty) name:+"*"
		If (host.lockedpanel=Self) name="build:"+name
		host.RefreshPanel Self
		PollSystem
	End Method
	
	Method SetLocked( bool )
		Local locked:TOpenCode
		locked=TOpenCode(host.lockedpanel)
		If locked And locked<>Self locked.SetLocked False
		name=StripDir(path)
		If (dirty) name:+"*"
		If (bool) 
			name="build:"+name
			host.lockedpanel=Self
		Else
			host.lockedpanel=Null			
		EndIf
		host.RefreshPanel Self
	End Method
	
	Method Help()
		Local	p,l$,a$
		If Not host.quickhelp Return
		p=TextAreaCursor(textarea,TEXTAREA_CHARS)
		a$=WordAtPos(cleansrc,p)
		If a$=helpcmd
			l$=host.quickhelp.link(a$)
			If l$ 
				host.helppanel.go host.bmxpath+l$
			EndIf
		Else
			helpcmd=a$
			helpstring$=host.quickhelp.help(a$)
			UpdateStatus	'host.setstatus helpstring$
		EndIf
	End Method

	Method Find()
		Local	p,l$,a$
		p=TextAreaCursor(textarea,TEXTAREA_CHARS)
		a$=WordAtPos(cleansrc,p)
		host.findreq.ShowFind a$
	End Method
		
	Method FindNext(s$)
		Local	p,l$
		If s seek=s Else s=seek
		p=TextAreaCursor(textarea,TEXTAREA_CHARS)
		p:+TextAreaSelLen(textarea,TEXTAREA_CHARS)
' case insensitive
		l$=s.toLower()
		p=cleansrcl.Find(l$,p)
		If p=-1 p=cleansrcl.Find(l$)
' case sensitive
'		p=cleansrc.Find(s$,p+1)
'		if p=-1 p=cleansrc.Find(s$)
		If p=-1
			Notify "Could not find "+s$
			Return False
		Else
			SelectTextAreaText textarea,p,Len s,TEXTAREA_CHARS
			UpdateCursor
			Return True
		EndIf
	End Method

	Method ReplaceAll(s$,r$)
		Local	p,c,l$,src$
		LockTextArea textarea
		c=TextAreaCursor(textarea,TEXTAREA_CHARS)
		s$=s.toLower()
		While True
			src=TextAreaText(textarea)
			l=src.ToLower()
			p=l.Find(s$,p)
			If p=-1 Exit
			SelectTextAreaText textarea,p,s.length
			UpdateCursor
			UpdateCode		
			SetTextAreaText textarea,r,p,s.length
			If p<c c=c+r.length-s.length			
			p=p+r.length
			SelectTextAreaText textarea,p,0
			UpdateCursor
			UpdateCode
		Wend
		SelectTextAreaText textarea,c,0
		UpdateCursor
		UnlockTextArea textarea
	End Method
	
	Method FindReplace(r$)
		Local	p,n,f$,x$
		p=r.Find(Chr(0))
		If p>0
			f$=r[..p]
			r$=r[p+1..]
			ReplaceAll f$,r$
		Else
			p=TextAreaCursor(textarea,TEXTAREA_CHARS)
			n=TextAreaSelLen(textarea,TEXTAREA_CHARS)
			If n=0 Return
			SetTextAreaText textarea,r$,p,n
			SelectTextAreaText textarea,p+Len r,0
			UpdateCursor
			UpdateCode		
		EndIf
		Return True
	End Method
	
	Method ReadSource(path$)
		Local	src$		
		src=LoadText(path)
		src=src.Replace(Chr(13),"")
		src=src.Replace(Chr(11),"")
		LockTextArea textarea
		SetTextAreaText textarea,src
		UnlockTextArea textarea
		filesrc=TextAreaText(textarea)
		cleansrc=""
		cleansrcl=""
		ActivateGadget textarea		
	End Method
	
	Method SaveSource(file$)
		Local	src$		
		If host.options.autobackup
			DeleteFile file+".bak"
			RenameFile file,file+".bak"
		EndIf		
		src=TextAreaText(textarea)
		filesrc=src
		src=src.Replace$(Chr(13),Chr(10))
		src=src.Replace$(Chr(11),"")
		Local txt$=src.Replace$(Chr(10),Chr(13)+Chr(10))		
		SaveText txt,file		
		path=host.FullPath$(file)
		dirty=True
		SetDirty False
		host.AddRecent(path$)
		Return True
	End Method

	Method BuildSource(quick,debug,gui,run)
		Local cmd$,out$,arg$		
		If isbmx Or isc Or iscpp
			cmd$=quote(host.bmkpath)
			cmd$:+" makeapp"
			If run cmd$:+" -x"
			If debug cmd$:+" -d" Else cmd$:+" -r"	'-v
			If gui cmd$:+" -t gui"
			If Not quick cmd$:+" -a"
			If debug 
				out$=StripExt(host.FullPath(path))+".debug"
				cmd$:+" -o "+quote(out$)+" "			'QUOTES+out$+QUOTES+" "
			EndIf		
			cmd$:+" "+quote(host.FullPath(path))
			If run
				arg$=host.GetCommandLine()
				If arg cmd$:+" "+arg
			EndIf
			host.execute cmd,"Building "+StripExt(StripDir(path))	',exe$
		Else
			If ishtml
				host.helppanel.Go "file://"+path 
			Else
'see what the system shell thinks of the file
				Local cd$=CurrentDir()
				ChangeDir ExtractDir(path)
				cmd=StripDir(path)
				host.execute cmd,"Building "+cmd
				ChangeDir cd
			EndIf			
		EndIf
'		print cmd
	End Method
	
	Method Save()
		Local	file$
		file=path
		If host.IsTempPath(path) 
			file=RequestFile("Save As",FILTERS,True,"")
			If file="" Return False
			If ExtractExt(file)="" file=file+".bmx"
			dirty=True
		EndIf
		If dirty SaveSource(file)
		Return True
	End Method
' common command interface

	Method Invoke(command,argument:Object=Null)
		Local	file$,ex$
		Local	p,res
		Select command
			Case TOOLSHOW
				host.SetCodeNode GetNode()
				host.SetTitle path				
				If textarea Edit
			Case TOOLCLOSE
				If dirty
					p=Proceed("Save changes to "+name)	'the current file?
					If p=-1 Return True
					If p=1 
						If Not Save() Return True
					EndIf
				EndIf
				If codenode codenode.detach;codenode=Null
				host.RemovePanel Self
			Case TOOLSAVE 
				Save
			Case TOOLQUICKSAVE 
				file=path
				If dirty SaveSource(file)
			Case TOOLSAVEAS
				file=path
				If host.IsTempPath(path) file$=""
				file=RequestFile("Save As",FILTERS,True,file)
				If file="" Return
				ex$=ExtractExt(file)
				If ex$="" 
					file=file+".bmx"
					isbmx=True
				Else
					isbmx=(ex.ToLower()="bmx")
					ishtml=(ex.ToLower()="html")
					isc=(ex.ToLower()="c")
					iscpp=(ex.ToLower()="cpp" Or ex.ToLower()="cxx")
				EndIf				
				SaveSource(file$)
				Refresh
				GetNode().Refresh
				setdirty False
				host.SetTitle path
			Case TOOLGOTO
				Local line=Int(String(argument))
				SelectTextAreaText textarea,line-1,0,TEXTAREA_LINES				
				UpdateCursor
				ActivateGadget textarea		
			Case TOOLFIND
				Find
			Case TOOLFINDNEXT
				res=FindNext(String(argument))
'				ActivateGadget textarea
				Return res		
			Case TOOLREPLACE
				Return FindReplace(String(argument))	
			Case TOOLBUILD
				BuildSource host.quickenabled,host.debugenabled,host.guienabled,False
			Case TOOLRUN 
				BuildSource host.quickenabled,host.debugenabled,host.guienabled,True
			Case TOOLLOCK
				SetLocked True
			Case TOOLUNLOCK
				SetLocked False			
			Case TOOLHELP
				Help
			Case TOOLUNDO
				Undo
			Case TOOLREDO
				Redo
			Case TOOLREFRESH
				Refresh
			Case TOOLCUT
				GadgetCut textarea
			Case TOOLCOPY
				GadgetCopy textarea
			Case TOOLPASTE
				GadgetPaste textarea
			Case TOOLSELECTALL 
				SelectTextAreaText textarea
			Case TOOLINDENT
				IndentCode
			Case TOOLOUTDENT
				OutdentCode
			Case TOOLPRINT
				GadgetPrint textarea
		End Select
	End Method
		
	Function CreateEditMenu:TGadget()
		Local	edit:TGadget
		edit=CreateMenu("&Edit",0,Null)
		CreateMenu "Quick Help",MENUQUICKHELP,edit
		CreateMenu "",0,edit
		CreateMenu "Cut",MENUCUT,edit
		CreateMenu "Copy",MENUCOPY,edit
		CreateMenu "Paste",MENUPASTE,edit
		CreateMenu "",0,edit
		CreateMenu "Select All",MENUSELECTALL,edit
		CreateMenu "",0,edit
		CreateMenu "Block Indent",MENUINDENT,edit
		CreateMenu "Block Outdent",MENUOUTDENT,edit
		CreateMenu "",0,edit
		CreateMenu "Find",MENUFIND,edit
		CreateMenu "Find Next",MENUFINDNEXT,edit
		CreateMenu "Replace",MENUREPLACE,edit
		CreateMenu "Goto Line",MENUGOTO,edit
		Return edit
	End Function
	
	Method MakePathTemp()
' prepends "." to file name with code borrowed from SaveAs		
		Local file$=ExtractDir(path)+"/."+StripDir(path)
		SaveSource(file$)
'		Refresh
		GetNode().Refresh
'		setdirty False
		host.SetTitle path
	End Method
	
	Function Create:TOpenCode(path$,host:TCodePlay)
		Local	code:TOpenCode
		Local	stream:TStream
		Local	isnew
		If path
			stream=ReadFile(path)
			If Not stream 
'				Notify "Open could not read from "+path		
				Return Null
			EndIf
			CloseFile stream
		Else
			TEMPCOUNT:+1
			path=host.bmxpath+"/tmp/untitled"+TEMPCOUNT+".bmx"
			isnew=True
		EndIf
		code=New TOpenCode
		code.host=host
		code.active=True
		code.path=host.FullPath(path)
		code.editmenu=CreateEditMenu()
		codeplay.addpanel(code)		
		code.textarea=CreateTextArea(0,0,ClientWidth(code.panel),ClientHeight(code.panel),code.panel,0)
		SetGadgetFilter code.textarea,code.FilterKey,code
		SetTextAreaText code.textarea,"~n"
		SetGadgetLayout code.textarea,1,1,1,1
		code.Refresh()
		
		If isnew 
			code.SaveSource path
			code.filesrc="~n"
			ActivateGadget code.textarea
		Else
			host.UpdateProgress "Reading Stream"
			code.ReadSource(path)
		EndIf
		
		If ExtractExt(path).toLower()="bmx" code.isbmx=True
		If ExtractExt(path).toLower()="c" code.isc=True
		If ExtractExt(path).toLower()="cpp" code.iscpp=True
		If ExtractExt(path).toLower()="cxx" code.iscpp=True
		If ExtractExt(path).toLower()="html" code.ishtml=True
		If ExtractExt(path).toLower()="htm" code.ishtml=True
		code.UpdateCode False
		code.filesrc=TextAreaText(code.textarea)
		Return code
	End Function

End Type

Type TRect
	Field		x,y,w,h

	Method Set(xpos,ypos,width,height)
		x=xpos;y=ypos;w=width;h=height
	End Method
	
	Method ToString$()
		Return ""+x+","+y+","+w+","+h
	End Method

	Method FromString(s$)
		Local	p,q,r
		p=s.Find(",")+1;If Not p Return
		q=s.Find(",",p)+1;If Not q Return
		r=s.Find(",",q)+1;If Not r Return
		x=Int(s[..p-1])
		y=Int(s[p..q-1])
		w=Int(s[q..r-1])
		h=Int(s[r..])
	End Method
	
	Method IsOutside(tx,ty,tw,th)
		If x+w<=tx Or y+h<=ty Return True
		If x>=tx+tw Or y>=ty+th Return True	
	End Method

End Type

Type TCodePlay

	Const EDITMODE=1
	Const DEBUGMODE=2
	
	Field	bmxpath$,bmkpath$
	Field	panels:TToolPanel[]
	Field	helppanel:THelpPanel
	Field	currentpanel:TToolPanel
	Field	output:TOutputPanel
	Field	lockedpanel:TToolPanel
	Field	activepanel:TToolPanel

	Field	cmdlinereq:TCmdLineRequester
	Field	cmdline$
	Field	syncmodsreq:TSyncModsRequester
	Field	gotoreq:TGotoRequester
	Field	findreq:TFindRequester
	Field	replacereq:TReplaceRequester
	Field	options:TOptionsRequester
'	Field	progress:TProgressRequester
	Field	activerequester:TRequester
	Field	projectreq:TProjectRequester
	Field	searchreq:TSearchRequester
	
	Field	eventhandlers:TList=New TList
	Field	window:TGadget,menubar:TGadget,toolbar:TGadget,client:TGadget,tabbar:TGadget
	Field	split:TSplitter
	Field	debugtree:TDebugTree

	Field	root:TNode
	Field	helproot:TNode
	Field	projects:TProjects
	Field	coderoot:TNode
	Field	navbar:TNavBar	

	Field	mode
	Field	debugcode:TOpenCode

	Field	quickenable:TGadget,quickenabled	'menu,state
	Field	debugenable:TGadget,debugenabled	'menu,state
	Field	guienable:TGadget,guienabled		'menu,state
	Field	quickhelp:TQuickHelp
	Field	running
	Field	recentmenu:TGadget
	Field	recentfiles:TList=New TList
	Field	recentmenus:TGadget[]
	Field	openlist:TList=New TList
	Field	openlock$
	Field	projlist:TList=New TList
	Field	winsize:TRect=New TRect
	Field	winmax,tooly,splitpos,debugview,navtab
	Field	progress

	Method CheckVersion$()
		Local	process:TProcess
		Local	bytes:Byte[]
		Local	cmd$,version$

		cmd$=bmxpath+"/bin/bcc"
?win32
		cmd:+".exe"
?
		cmd=Quote(cmd)
		process=CreateProcess(cmd$,HIDECONSOLE)
		If process
			While True
				bytes=process.pipe.ReadPipe()
				If bytes
					version:+String.FromBytes(bytes,Len bytes)
				EndIf
				If Not process.status() Exit				
				Delay 10
			Wend
		EndIf

		If version=""
			Notify "Unable to locate required files.~n~nPlease reinstall BlitzMax to repair this problem."
			End
		EndIf
		
		BCC_VERSION=version.Trim()
		
'		print "bcc version="+version

		If version.find("(expired)")>-1	'Demo timed out
			Notify "This demo version of BlitzMax has expired.~n~nPlease visit www.blitzbasic.com to buy the full version."
			End
		EndIf

		If version.find("Demo Version")>-1	'Demo timed out
			is_demo=True
			Notify version+"~nTo purchase the full version please visit www.blitzbasic.com."
			Notify ABOUTDEMO
		EndIf
		
	End Method
	
	Method OpenProgress(message$)
'		progress.Open message
		DisableGadget window
		SetStatus message
		progress=-1
	End Method

	Method CloseProgress()
'		progress.Hide
		SetStatus ""
		EnableGadget window
		progress=0
	End Method
	
	Method UpdateProgress(message$,value=0)		'returns false if cancelled
'		Return progress.Update(message,value)
		If progress
			If progress/5<>value/5
				SetStatus message+" "+value+"%"
				progress=value
'				Pollsystem
			EndIf
		EndIf
	End Method

	Method FullPath$(path$)
		If path[..8]="$BMXPATH" path=bmxpath+path[8..]
		path=RealPath(path)
?win32
		path=path.Replace("\","/")
?
		Return path
	End Method

	Method IsTempPath(path$)
		If path[..Len bmxpath+5]=bmxpath+"/tmp/" Return True
	End Method

	Method ReadConfig()
		Local	stream:TStream
		Local	f$,p,a$,b$
' defaults		
		Local wh=GadgetHeight(Desktop())-80'32
		Local ww=wh
		Local wx=(GadgetWidth(Desktop())-ww)/2
		Local wy=(GadgetHeight(Desktop())-wh)/2
		winsize.set( wx,wy,ww,wh )
		quickenabled=False
		debugenabled=True
		guienabled=True	
		splitpos=ww-200
' read ini
		stream=ReadFile(bmxpath+"/cfg/ide.ini")
		If Not stream 
			projlist.AddLast "samples|samples"
			projlist.AddLast "brl.mod|mod/brl.mod"
			projlist.AddLast "pub.mod|mod/pub.mod"
			projlist.AddLast "src|src"
			Return
		EndIf
		options.read(stream)		
		options.Snapshot
		While Not stream.Eof()
			f$=stream.ReadLine()
			p=f.find("=")
			If p=-1 Continue
			a$=f[..p]
			b$=f[p+1..]
			Select a$
				Case "ide_version"
				
				Case "file_recent"
					recentfiles.addlast b$
				Case "file_open"
					openlist.addlast b$
				Case "prg_quick"
					quickenabled=Int(b$)
				Case "prg_debug"
					debugenabled=Int(b$)
				Case "prg_gui"
					guienabled=Int(b$)
				Case "cmd_line"
					cmdline=b$
				Case "prg_locked"
					openlock=b$
				Case "win_size"
					winsize.FromString(b$)
				Case "win_max"
					winmax=Int(b$)
				Case "split_pos"
					splitpos=Int(b$)
				Case "proj_node"
					projlist.AddLast b$
				Case "sync_state"
					syncmodsreq.FromString b$
			End Select
		Wend
		stream.close		
	End Method
	
	Method WriteConfig()
		Local	panel:TToolPanel
		Local	stream:TStream
		Local	node:TNode
		Local	f$
		stream=WriteFile(bmxpath+"/cfg/ide.ini")
		If Not stream Return
' options
		options.write(stream)
' defaults		
		stream.WriteLine "[Defaults]"
		stream.WriteLine "ide_version="+IDE_VERSION$
		stream.WriteLine "prg_quick="+quickenabled
		stream.WriteLine "prg_debug="+debugenabled
		stream.WriteLine "prg_gui="+guienabled
		stream.WriteLine "win_size="+winsize.ToString()
		stream.WriteLine "win_max="+winmax
		stream.WriteLine "split_pos="+split.pos
		stream.WriteLine "cmd_line="+cmdline
		stream.WriteLine "sync_state="+syncmodsreq.ToString()
		If lockedpanel stream.WriteLine "prg_locked="+lockedpanel.path
		For f$=EachIn recentfiles
			stream.WriteLine "file_recent="+f$
		Next
		For panel=EachIn panels
			f$=panel.path
			If f$ And Not IsTempPath(f$) stream.WriteLine "file_open="+f$
		Next
		projects.write(stream)	
		stream.close
	End Method
	
	Method CloseAll(dontask)	'returns true if successful
		Local	panel:TToolPanel
		Local	mypanels:TToolPanel[]
		Local	cancel,count

		For panel=EachIn panels
			If TOpenCode(panel) count=count+1
		Next
		If count=0 dontask=True
		If dontask Or Confirm("MaxIDE needs to close all documents before continuing")
			mypanels=panels
			For panel=EachIn mypanels
				If panel.invoke(TOOLCLOSE) cancel=True
			Next
			Return Not cancel
		EndIf
	End Method

	Method Quit()
		WriteConfig
		If CloseAll(True) running=False
	End Method

	Method DebugExit()
		If debugcode 
			debugcode.Edit		'restore cursor etc.	
			debugcode=Null
		EndIf
		SetMode EDITMODE
	End Method
		
	Method DebugSource(path$,line,column)
		Local	code:TOpenCode
		path=FullPath(path)
		code=OpenSource(path)
		If code=Null
			Notify("Failed to Open "+path)
			Return
		EndIf
		If debugcode And debugcode<>code debugcode.Edit		'restore cusor etc.	
		debugcode=code
		debugcode.debug(line,column)	
		ActivateWindow window
		PollSystem
	End Method
	
	Method SetMode(m)
		If mode=m Return
		ActivateWindow window
		Select m
		Case DEBUGMODE
			navtab=navbar.SelectedView()
			navbar.SelectView debugview
		Case EDITMODE
			navbar.SelectView navtab
		End Select
		mode=m
		RefreshToolbar
	End Method
	
	Method RefreshToolbar()		
		Local	i
' sourceedit buttons
		If THelpPanel(CurrentPanel)
			DisableGadgetItem toolbar,2
		Else
			EnableGadgetItem toolbar,2
		EndIf
		If TOpenCode(CurrentPanel)
			EnableGadgetItem toolbar,3
			For i=5 To 8
				EnableGadgetItem toolbar,i
			Next
		Else
			DisableGadgetItem toolbar,3
			For i=5 To 8
				DisableGadgetItem toolbar,i
			Next			
		EndIf
' debug buttons
		If mode=DEBUGMODE And debugtree.cancontinue
			For i=12 To 14
				EnableGadgetItem toolbar,i
			Next
		Else
			For i=12 To 14
				DisableGadgetItem toolbar,i
			Next
		EndIf
' stop button		
		If output And output.process
			EnableGadgetItem toolbar,15
		Else
			DisableGadgetItem toolbar,15
		EndIf		
	End Method
	
	Method IsSourceOpen(path$)
		Local	panel:TToolPanel
		Local	p$
		p$=FullPath(path)
		For panel=EachIn panels
			If panel.path=p Return True
		Next
	End Method
	
	Method OpenSource:TOpenCode(path$)
		Local	code:TOpenCode
		Local	panel:TToolPanel
		Local	ext$,p$
		If path$="." 
			path$=RequestFile("Open File",FILTERS )
			If path$="" Return
		EndIf
' check if already open
		p$=FullPath(path).ToLower()
		For panel=EachIn panels
			If panel.path.ToLower()=p
				SelectPanel panel
				Return TOpenCode(panel)
			EndIf
		Next
' open based on extension		
'		Select ExtractExt(Upper(path$))
'		Case "BMX","TXT","BB","CPP","C","S","I","H","HTML","CSS","BAT","FS","VS","README",""
			OpenProgress "Loading "+StripDir(path)
			code=TOpenCode.Create(path,Self)
			If code 
				AddRecent code.path
'				opencoderoot.Append code.GetNode()
'				opencoderoot.Refresh 
'				opencoderoot.Open
			EndIf			
			CloseProgress
			If code 
				ActivateGadget code.textarea		
				code.GetNode().Refresh
			EndIf
			Return code
'		end select
	End Method
	
	Method AddRecent(path$)
		Local	f$
		For f$=EachIn recentfiles
			If f$=path$ recentfiles.Remove(f$);Exit
		Next
		recentfiles.AddFirst(path$)
		RefreshRecentFiles
		UpdateWindowMenu window
	End Method
	
	Method RefreshRecentFiles()
		Local	n,f$
		Local	m:TGadget
		For m=EachIn recentmenus
			FreeMenu m
		Next
		n=Min(recentfiles.count(),16)
		recentmenus=New TGadget[n]
		n=0
		For f$=EachIn recentfiles
			recentmenus[n]=CreateMenu(f$,MENURECENT+n,recentmenu)
			n:+1
			If n=16 Exit
		Next
	End Method
	
	Method BuildModules(buildall)
		Local cmd$,out$,exe$
		output.stop
		SaveAll
		cmd$=quote(bmkpath)
		cmd$:+" makemods "
'		If debugenabled cmd$:+"-d " Else cmd$:+"-r "
		If buildall cmd$:+"-a "
		Execute cmd,"Building Modules"
	End Method

	Method ImportBB()
		Local	f$,cmd$,path$
		f$=RequestFile("Import .bb File","bb" )
		If Not f$ Return
		cmd$=quote(bmkpath$)
		cmd$:+" convertbb "
		cmd$:+quote(FullPath(f$))
		Execute cmd,"Converting "+StripExt(StripDir(f$))
		output.wait
		OpenSource(StripExt(f$)+".bmx")
	End Method

	Method GetCommandLine$()
		Return cmdline
	End Method

	Method SetCommandLine(text$)
		cmdline=text
	End Method
	
	Method SetStatus(text$)
		SetStatusText window,text
	End Method

	Method Execute(cmd$,mess$="",post$="",home=True)
		If Not output output=TOutputPanel.Create(Self)
		output.execute cmd$,mess$,post$,home
	End Method

	Method SelectError(path$,column,line)
		Local	panel:TToolPanel,found
		For panel=EachIn panels
			If panel.path=path found=True;Exit
		Next
		If Not found panel=OpenSource(path)
		If panel
			SelectPanel panel
			panel.Invoke TOOLGOTO,String(line)
		EndIf
	End Method
	
	Method ParseError(err$)
		Local		mess$,file$,p,q
		Local		line,column
' bcc error
		If err$[..13]="Compile Error"
			err=err[14..]
			p=err.find(EOL$)
			If p=-1 p=Len err
			mess=err[..p]
			err=err[p+1..]
			If err[..1]="["
				p=err.find("]")
				If p=-1 p=Len err
				file$=err[1..p]
				p=file.find(";")+1
				If p=0 p=Len err
				q=file.find(";",p)+1
				If q=0 q=Len err
				line=Int(file[p..q-1])
				column=Int(file[q..])
				file=FullPath(file[..p-1])				
				SelectError file,column,line
			EndIf
			Notify "Compile Error"+EOL+mess
			SetStatus mess
			Return
		EndIf
' gcc error
		err=err.Replace(EOL+"   "," ")
		While err
			p=err.find(EOL)
			If p=-1 p=(Len err)-1
			mess=err[..p]
			err=err[p+1..]
			p=0
			While True
				p=mess.Find(":",p)+1
				If p=0 Exit
				q=mess.Find(":",p)
				If q<>-1
					file=mess[..p-1]
					line=Int(mess[p..q])
					If line
						mess=mess[q+1..]
						SelectError file,column,line
						Notify "Compile Error"+EOL+mess
						Return
					EndIf
					p=q+1
				EndIf
			Wend
		Wend		
	End Method
		
	Method AddPanel(tabpanel:TToolPanel)
		Local	panel:TGadget,index
		index=CountGadgetItems(tabbar)
		If panels.length<=index panels=panels[..index+1]
		AddGadgetItem(tabbar,tabpanel.name$,True)
		
		panel=CreatePanel(0,0,ClientWidth(tabbar),ClientHeight(tabbar),tabbar,0)	'name		
		SetGadgetLayout panel,1,1,1,1
		tabpanel.panel=panel
		
		tabpanel.index=index
		panels[index]=tabpanel
		SelectPanel tabpanel
		eventhandlers.addlast tabpanel
	End Method

	Method AddHandler(handler:TEventHandler)
		eventhandlers.addlast handler
	End Method

	Method RemovePanel(tabpanel:TToolPanel)
		Local p:TToolPanel[]
		Local index
		eventhandlers.remove tabpanel
' unset debugcode
		If debugcode=tabpanel debugcode=Null		
' activate next panel
		If tabpanel=activepanel activepanel=helppanel
		If tabpanel=lockedpanel lockedpanel=Null
		If tabpanel=currentpanel
			index=tabpanel.index+1
			If index>=panels.length index=panels.length-2
			SelectPanel panels[index]
		EndIf
' remove from array
		p=panels
		panels=panels[..panels.length-1]
		For index=tabpanel.index To panels.length-1
			panels[index]=p[index+1]
			panels[index].index=index
		Next
' remove gadget	- simon come here,  placing before remove needs fix in fltk
		FreeGadget tabpanel.panel
		RemoveGadgetItem tabbar,tabpanel.index
		tabpanel.panel=Null
	End Method
		
	Method SetRequester(req:TRequester)
		activerequester=req
	End Method
	
	Method SetTitle(title$="")
		If title title=" - "+title
		SetGadgetText window,"MaxIDE"+title
	End Method
	
	Method SelectPanel(panel:TToolPanel)	
		Local	current:TToolPanel
		current=currentpanel
		currentpanel=panel
		If current And current<>currentpanel
			SelectGadgetItem tabbar,panel.index
			ShowGadget panel.panel
			If panel.active activepanel=panel
			HideGadget current.panel
			RefreshToolbar
		EndIf
		currentpanel.Invoke TOOLSHOW
	End Method
		
	Method RefreshPanel(panel:TToolPanel)	'call after a name change
		ModifyGadgetItem( tabbar,panel.index,panel.name )	
	End Method

	Function OutsideDesktop(winrect:TRect)
		Local desk:TGadget,x,y,w,h
		desk=Desktop()
		x=GadgetX(desk)
		y=GadgetY(desk)
		w=GadgetWidth(desk)
		h=GadgetHeight(desk)
		Return winrect.IsOutside(x,y,w,h)
	End Function

	Method SetCodeNode(code:TNode)
		Local node:TNode
		If coderoot.kids.count() node=TNode(coderoot.kids.First())
		If node=code Return
		If node node.Detach
		If code
			coderoot.Append code
			coderoot.Refresh 
			coderoot.Open
			code.Open
		EndIf
	End Method

	Method Initialize()		
		Local	open:TOpenCode
		Local	i,dir$,nomods,pname$,p
		Local	stream:TStream
		
		Try
			bmxpath=BlitzMaxPath()
		Catch err$
			Notify "Could not find BlitzMax compiler (bin/bcc), please Reinstall~nappdir="+AppDir
			End
		EndTry
		
		CreateDir BlitzMaxPath()+"/tmp"
		
		bmkpath=bmxpath+"/bin/bmk"
?win32
		bmkpath:+".exe"
?
		dir$=bmxpath+"/mod"
		If FileType(dir)=0
			If Not CreateDir(dir)
				Notify "Failed to Create Module Directory "+dir
				End
			EndIf
			nomods=True
		EndIf
		dir$=bmxpath+"/tmp"
		If FileType(dir)=0
			If Not CreateDir(dir)
				Notify "Failed to Create Temp Directory "+dir
				End
			EndIf
		EndIf
		dir$=bmxpath+"/cfg"
		If FileType(dir)=0
			If Not CreateDir(dir)
				Notify "Failed to Create Config Directory "+dir
				End
			EndIf
		EndIf

		cmdlinereq=TCmdLineRequester.Create(Self)
		syncmodsreq=TSyncModsRequester.Create(Self)
		gotoreq=TGotoRequester.Create(Self)
		findreq=TFindRequester.Create(Self)
		replacereq=TReplaceRequester.Create(Self)
		options=TOptionsRequester.Create(Self)
'		progress=TProgressRequester.Create(Self)
		projectreq=TProjectRequester.Create(Self)
		searchreq=TSearchRequester.Create(Self)

		ReadConfig
		If OutsideDesktop(winsize)
			winsize.set(20,20,760,540)		
		EndIf	

		window=CreateWindow("MaxIDE",winsize.x,winsize.y,winsize.w,winsize.h,Null,15|WINDOW_HIDDEN|WINDOW_ACCEPTFILES)	
		If winmax MaximizeWindow(window)

		toolbar=CreateToolBar("incbin::icons.PNG",0,0,0,0,window )
		SetToolBarTips toolbar,["New","Open","Close","Save","","Cut","Copy","Paste","Find","","Build","Build And Run","Step","Step In","Step Out","Stop"		,"","Home","Back","Forward"		]
'		InsertToolBarSeparator toolbar,5

		If options.showtoolbar
			tooly=GadgetHeight(toolbar)
		Else
			HideGadget toolbar
			tooly=0
		EndIf

?MacOS
		client=window
' cludge for window growing from adding of toolbar
		If Not winmax SetGadgetShape window,winsize.x,winsize.y,winsize.w,winsize.h
?
		If Not client
			client=CreatePanel(0,tooly,ClientWidth(window),ClientHeight(window)-tooly,window,4)
			SetGadgetLayout client,1,1,1,1
		EndIf

		tabbar=CreateTabber(0,0,0,0,client)	'clientwidth(window),clientheight(window)-tooly,window,0)
		debugtree=TDebugTree.CreateDebugTree(Self)

		root=TNode.Create("Home")
		helproot=root.AddNode("Help")
		helproot.Open
		
		projects=TProjects.CreateProjects(Self)		
		root.Append projects
		projects.Open

'		opencoderoot=root.AddNode("Open")
		coderoot=TNode.Create("Code")	'root.AddNode("Open")
		coderoot.Open

		navbar=TNavBar.Create(Self)

		navbar.AddView root
		navbar.AddView coderoot
		debugview=navbar.AddView(debugtree)
		navbar.SelectView 0
		
		split=TSplitter.Create(TSplitter.VERTICAL,splitpos,options.navswap,tabbar,navbar.tabber)		'treeview)

		AddHandler navbar
		AddHandler split
	
		SetMode EDITMODE

		CreateTimer(10)		
		quickhelp=TQuickHelp.LoadCommandsTxt(bmxpath)
		helppanel=THelpPanel.Create(Self)
		
		output=TOutputPanel.Create(Self)
		
		activepanel=helppanel
		InitMenu
		InitHotkeys
		ShowGadget window	
		RefreshAll
		PollSystem	'allow repaint

		helppanel.Home
	
' open files from .ini restorelist		
		If options.restoreopenfiles
			For Local f$=EachIn openlist
				open=OpenSource(f$)
				If open And f$=openlock open.SetLocked(True) 
			Next
		EndIf
' open files specified in command line		
		For i=1 To AppArgs.length-1
			open=OpenSource(AppArgs[i])
		Next
' scan projects in projlist		
		For pname$=EachIn projlist
			p=pname.Find("|")
			If p<>-1
				projects.Add pname[..p],pname[p+1..]
			EndIf
		Next
		
'		RefreshAll
'		showgadget window
		PollSystem
		running=True
	
		CheckVersion
		If nomods syncmodsreq.Show	
		
	End Method
	
	Method DocMods()
		Local cmd$
		cmd$=quote(bmxpath+"/bin/docmods")
		execute cmd,"Document Modules",MENUTRIGGERSYNCDOCS
	End Method
		
	Method SyncDocs()
		helppanel.SyncDocs()
		quickhelp=TQuickHelp.LoadCommandsTxt(bmxpath)
	End Method

	Method InitMenu()
		Local menu:TGadget,file:TGadget,edit:TGadget,program:TGadget,tools:TGadget
		Local help:TGadget,options:TGadget
		Local buildmods:TGadget,buildallmods:TGadget,syncmods:TGadget,docmods:TGadget

		Const MENUMOD=MODIFIER_COMMAND

		menu=WindowMenu(window)

		file=CreateMenu("&File",0,menu)
		CreateMenu "&New",MENUNEW,file,KEY_N,MENUMOD
		CreateMenu "&Open...",MENUOPEN,file,KEY_O,MENUMOD
		recentmenu=CreateMenu("Open &Recent",0,file)
		CreateMenu "&Close",MENUCLOSE,file,KEY_W,MENUMOD
		CreateMenu "Close All",MENUCLOSEALL,file,KEY_W,MENUMOD|MODIFIER_SHIFT
		CreateMenu "",0,file
		CreateMenu "&Save",MENUSAVE,file,KEY_S,MENUMOD
		CreateMenu "Save &As",MENUSAVEAS,file,KEY_S,MENUMOD|MODIFIER_SHIFT
		CreateMenu "Save A&ll",MENUSAVEALL,file
		CreateMenu "",0,file
?MacOS
		CreateMenu "&Next File",MENUNEXT,file,KEY_RIGHT,MENUMOD
		CreateMenu "&Previous File",MENUPREV,file,KEY_LEFT,MENUMOD
?Win32
		CreateMenu "&Next File",MENUNEXT,file,KEY_RIGHT,MENUMOD
		CreateMenu "&Previous File",MENUPREV,file,KEY_LEFT,MENUMOD
?Linux
		CreateMenu "&Next File",MENUNEXT,file,KEY_RIGHT,MODIFIER_ALT
		CreateMenu "&Previous File",MENUPREV,file,KEY_LEFT,MODIFIER_ALT
?
		CreateMenu "",0,file
		CreateMenu "IDE Options...",MENUOPTIONS,file
		CreateMenu "&Project Manager...",MENUPROJECTMANAGER,file
		CreateMenu "&Import BB Project...",MENUIMPORTBB,file	
		CreateMenu "",0,file
		CreateMenu "Print...",MENUPRINT,file
?Win32
		CreateMenu "",0,file
		CreateMenu "E&xit",MENUQUIT,file
?Linux
		CreateMenu "",0,file
		CreateMenu "E&xit",MENUQUIT,file
?
		edit=CreateMenu("&Edit",0,menu)
		CreateMenu "&Undo",MENUUNDO,edit,KEY_Z,MENUMOD
?MacOS
		CreateMenu "&Redo",MENUREDO,edit,KEY_Z,MENUMOD|MODIFIER_SHIFT
?Win32
		CreateMenu "&Redo",MENUREDO,edit,KEY_Y,MENUMOD
?Linux
		CreateMenu "&Redo",MENUREDO,edit,KEY_Y,MENUMOD
?
		CreateMenu "",0,edit
		CreateMenu "Cu&t",MENUCUT,edit,KEY_X,MENUMOD
		CreateMenu "&Copy",MENUCOPY,edit,KEY_C,MENUMOD
		CreateMenu "&Paste",MENUPASTE,edit,KEY_V,MENUMOD
		CreateMenu "",0,edit
		CreateMenu "Select &All",MENUSELECTALL,edit,KEY_A,MENUMOD
		CreateMenu "",0,edit
		CreateMenu "Block Indent",MENUINDENT,edit,KEY_CLOSEBRACKET,MENUMOD
		CreateMenu "Block Outdent",MENUOUTDENT,edit,KEY_OPENBRACKET,MENUMOD
		CreateMenu "",0,edit
		CreateMenu "&Find...",MENUFIND,edit,KEY_F,MENUMOD
?MacOS
		CreateMenu "Find Next",MENUFINDNEXT,edit,KEY_G,MENUMOD
		CreateMenu "&Replace...",MENUREPLACE,edit,KEY_H,MENUMOD
		CreateMenu "&Goto Line...",MENUGOTO,edit,KEY_L,MENUMOD
?Win32
		CreateMenu "Find Next",MENUFINDNEXT,edit,KEY_F3
		CreateMenu "&Replace...",MENUREPLACE,edit,KEY_H,MENUMOD
		CreateMenu "&Goto Line...",MENUGOTO,edit,KEY_G,MENUMOD
?Linux
		CreateMenu "Find Next",MENUFINDNEXT,edit,KEY_F3
		CreateMenu "&Replace...",MENUREPLACE,edit,KEY_H,MENUMOD
		CreateMenu "&Goto Line...",MENUGOTO,edit,KEY_G,MENUMOD
?
		program=CreateMenu("&Program",0,menu)
		CreateMenu "&Build",MENUBUILD,program,KEY_B,MENUMOD
		CreateMenu "Build and &Run",MENURUN,program,KEY_R,MENUMOD
		CreateMenu "Command &Line...",MENUCOMMANDLINE,program
		CreateMenu "",0,program
		CreateMenu "&Step",MENUSTEP,program,KEY_F9
		CreateMenu "Step &In",MENUSTEPIN,program,KEY_F10
		CreateMenu "Step &Out",MENUSTEPOUT,program,KEY_F11
		CreateMenu "&Halt",MENUSTOP,program
		options=CreateMenu("Build Options",0,program)
		quickenable=CreateMenu("Quick Build",MENUQUICKENABLED,options)
		debugenable=CreateMenu("Debug Build",MENUDEBUGENABLED,options)
		guienable=CreateMenu("Build GUI App",MENUGUIENABLED,options)
		CreateMenu "",0,program
		CreateMenu "&Lock Build File",MENULOCKBUILD,program
		CreateMenu "&Unlock Build File",MENUUNLOCKBUILD,program
		CreateMenu "",0,program
		syncmods=CreateMenu("&Synchronize Modules...",MENUSYNCMODS,program)
		CreateMenu "",0,program
		buildmods=CreateMenu("Build &Modules",MENUBUILDMODULES,program,KEY_D,MENUMOD)
		buildallmods=CreateMenu("Rebuild &All Modules",MENUBUILDALLMODULES,program)
		docmods=CreateMenu("&Document Modules...",MENUDOCMODS,program)
		
		help=CreateMenu("&Help",0,menu)
		CreateMenu "&Home",MENUHOME,help
		CreateMenu "&Back",MENUBACK,help
		CreateMenu "&Forward",MENUFORWARD,help
		CreateMenu "&Quick Help",MENUQUICKHELP,help,KEY_F1
		CreateMenu "&About BlitzMax",MENUABOUT,help
		
		If quickenabled CheckMenu quickenable
		If debugenabled CheckMenu debugenable
		If guienabled CheckMenu guienable
		
?win32		
		Local mingw$=getenv_("MINGW")
		If Not mingw
			DisableMenu buildmods
			DisableMenu buildallmods
		EndIf
?		
		If is_demo
			DisableMenu syncmods
		EndIf
		
		RefreshRecentFiles
		UpdateWindowMenu window
	End Method

	Method RunCode()
		If mode=DEBUGMODE And debugtree.cancontinue
			output.go
			Return
		EndIf
		output.stop
		SaveAll
		If lockedpanel
			lockedpanel.invoke TOOLRUN
		Else
			activepanel.invoke TOOLRUN
		EndIf
	End Method
	
	Method BuildCode()
		output.stop
		SaveAll
		If lockedpanel
			lockedpanel.invoke TOOLBUILD
		Else
			activepanel.invoke TOOLBUILD
		EndIf
	End Method
		
		
	Method AddEventHotKey(key,mods,id,data)
		SetHotKeyEvent key,mods,CreateEvent(id,Null,data)
	End Method
		
	Method InitHotkeys()
		AddEventHotKey KEY_F5,MODIFIER_NONE,EVENT_MENUACTION,MENURUN
		AddEventHotKey KEY_F7,MODIFIER_NONE,EVENT_MENUACTION,MENUBUILD
	End Method
		
	Method SaveAll()
		Local	panel:TToolPanel
		For panel=EachIn panels
			panel.invoke TOOLQUICKSAVE						
		Next
	End Method
	
	Method RefreshAll()
		Local	panel:TToolPanel
' flip navbar
		split.SetFlip options.navswap		
' hide/show toolbar
		If options.showtoolbar
			If GadgetHidden(toolbar) 
				tooly=GadgetHeight(toolbar)
				ShowGadget toolbar
				SetGadgetShape client,0,tooly,ClientWidth(window),ClientHeight(window)-tooly				
'				SetGadgetShape tabbar,0,tooly,clientwidth(window),clientheight(window)-tooly
			EndIf
		Else
			If Not GadgetHidden(toolbar)
				tooly=0
				HideGadget toolbar
				SetGadgetShape client,0,tooly,ClientWidth(window),ClientHeight(window)-tooly
'				SetGadgetShape tabbar,0,tooly,clientwidth(window),clientheight(window)-tooly
			EndIf
		EndIf
' refresh panels
		For panel=EachIn panels
			panel.invoke TOOLREFRESH						
		Next
' refresh navbar
		navbar.invoke TOOLREFRESH
	End Method

	Method SnapshotWindow()
		If WindowMaximized(window)
			winmax=True
		Else
			If Not WindowMinimized(window)
				winmax=False
				winsize.x=GadgetX(window)
				winsize.y=GadgetY(window)
				winsize.w=GadgetWidth(window)
				winsize.h=GadgetHeight(window)
			EndIf
		EndIf
	End Method
	
	Method OnMenu(menu)
		Local	index

		Select menu
			Case MENUNEW
				OpenSource ""
			Case MENUOPEN
				OpenSource "."
			Case MENUCLOSE
				currentpanel.invoke TOOLCLOSE						
			Case MENUCLOSEALL
				CloseAll True					
			Case MENUSAVE
				currentpanel.invoke TOOLSAVE						
			Case MENUSAVEAS			
				currentpanel.invoke TOOLSAVEAS						
			Case MENUSAVEALL
				SaveAll
			Case MENUPRINT
				currentpanel.invoke TOOLPRINT						
			Case MENUQUIT
				Quit

			Case MENUGOTO
				gotoreq.Show
			Case MENUFIND
				currentpanel.invoke TOOLFIND
			Case MENUFINDNEXT
				currentpanel.invoke TOOLFINDNEXT
			Case MENUREPLACE
				replacereq.Show

			Case MENUUNDO currentpanel.invoke TOOLUNDO
			Case MENUREDO currentpanel.invoke TOOLREDO

			Case MENUCUT currentpanel.invoke TOOLCUT
			Case MENUCOPY currentpanel.invoke TOOLCOPY
			Case MENUPASTE currentpanel.invoke TOOLPASTE
			Case MENUSELECTALL currentpanel.invoke TOOLSELECTALL
										
			Case MENUBUILD
				BuildCode 
			Case MENURUN 
				RunCode

			Case MENUBUILDMODULES
				If CheckDemo() BuildModules False
			Case MENUBUILDALLMODULES
				If CheckDemo() BuildModules True	
			Case MENUSYNCMODS
				If CheckDemo() And CloseAll(False) syncmodsreq.Show
			Case MENUDOCMODS
				If CheckDemo() And CloseAll(False) DocMods
			Case MENUTRIGGERDOCMODS
				DocMods
			Case MENUTRIGGERSYNCDOCS
				SyncDocs
				
			Case MENUSTEP If output output.stepover
			Case MENUSTEPIN If output output.stepin
			Case MENUSTEPOUT If output output.stepout
			Case MENUSTOP If output output.stop

			Case MENULOCKBUILD
				activepanel.invoke TOOLLOCK
			Case MENUUNLOCKBUILD
				If lockedpanel lockedpanel.invoke TOOLUNLOCK
			
			Case MENUCOMMANDLINE cmdlinereq.Show
			
			Case MENUQUICKENABLED
				If quickenabled
					quickenabled=False
					UncheckMenu quickenable							
				Else
					quickenabled=True
					CheckMenu quickenable
				EndIf
				UpdateWindowMenu window

			Case MENUDEBUGENABLED
				If debugenabled
					debugenabled=False
					UncheckMenu debugenable							
				Else
					debugenabled=True
					CheckMenu debugenable
				EndIf
				UpdateWindowMenu window
				
			Case MENUGUIENABLED
				If guienabled
					guienabled=False
					UncheckMenu guienable							
				Else
					guienabled=True
					CheckMenu guienable
				EndIf
				UpdateWindowMenu window

			Case MENUIMPORTBB
				ImportBB
				
			Case MENUFINDINFILES
				searchreq.Show
			Case MENUPROJECTMANAGER
				projectreq.Open projects
			Case MENUSHOWCONSOLE
				If output output.Open

			Case MENUOPTIONS
				options.Show
				
			Case MENUNEXT
				If Not currentpanel Return
				index=currentpanel.index+1
				If index=panels.length index=0
				SelectPanel panels[index]

			Case MENUPREV
				If Not currentpanel Return
				index=currentpanel.index-1
				If index<0 index=panels.length-1
				SelectPanel panels[index]
			
			Case MENUQUICKHELP 
				currentpanel.invoke TOOLHELP
			
			Case MENUHOME
				helppanel.Home
				SelectPanel helppanel
			Case MENUBACK
				helppanel.Back
				SelectPanel helppanel
			Case MENUFORWARD
				helppanel.Forward
				SelectPanel helppanel
			Case MENUABOUT
				Local typ$
				If is_demo typ="Demo" Else typ="Release"
				Local msg$=ABOUT.Replace( "{bcc_version}",BCC_VERSION )
				Notify msg
			Case MENUINDENT
				currentpanel.invoke TOOLINDENT
			Case MENUOUTDENT
				currentpanel.invoke TOOLOUTDENT
				
			Case MENUNEWVIEW
				navbar.invoke TOOLNEWVIEW
				
		End Select
		
		If menu>=MENURECENT
			Local f$=String(recentfiles.ValueAtIndex(menu-MENURECENT))
			If f$ OpenSource f$
		EndIf
	End Method
	
	Method poll()
		Local	handler:TEventHandler
		Local	requester:TRequester
		Local	src:TGadget,file$,EventID
		Local	index


		EventID=WaitEvent()
		
		If activerequester
			activerequester.Poll
			Return
		EndIf

		For handler=EachIn eventhandlers
			handler.OnEvent()
		Next
		Select EventID
			Case EVENT_GADGETACTION
				Select EventSource()
					Case toolbar
						Select EventData()
							Case 0 OpenSource ""
							Case 1 OpenSource "."
							Case 2 currentpanel.invoke TOOLCLOSE
							Case 3 currentpanel.invoke TOOLSAVE	
							Case 5 currentpanel.invoke TOOLCUT
							Case 6 currentpanel.invoke TOOLCOPY
							Case 7 currentpanel.invoke TOOLPASTE
							Case 8 currentpanel.invoke TOOLFIND
							Case 10 BuildCode
							Case 11 RunCode
							Case 12 If output output.stepover
							Case 13 If output output.stepin
							Case 14 If output output.stepout
							Case 15 If output output.stop
							Case 17 helppanel.Home;SelectPanel helppanel
							Case 18 helppanel.Back;SelectPanel helppanel
							Case 19 helppanel.Forward;SelectPanel helppanel
						End Select
						
					Case tabbar
						index=EventData()
						If index>=0 And index<panels.length
							SelectPanel panels[index]
						EndIf
				End Select
				
			Case EVENT_APPOPENFILE
				OpenSource EventText()
				
			Case EVENT_APPTERMINATE
				Quit

			Case EVENT_WINDOWACTIVATE
				SelectPanel currentpanel
				
			Case EVENT_WINDOWCLOSE
				src=TGadget(EventSource())
				For requester=EachIn eventhandlers
					If src=requester.window requester.Hide
				Next
				If src=window Quit

			Case EVENT_WINDOWMOVE
				If EventSource()=window SnapshotWindow				
				
			Case EVENT_WINDOWSIZE
				If EventSource()=window 
					SnapshotWindow
					split.Resize
				EndIf
				
			Case EVENT_WINDOWACCEPT
				OpenSource String( EventExtra() )
			Case EVENT_MENUACTION
				OnMenu EventData()
			Case EVENT_APPTERMINATE
				OnMenu MENUQUIT

		End Select
	End Method

End Type




kfprimm2006
[codebox]?


Perturbatio2006
[codebox]?


can't in code archives


Yan2006
Can in the comments (part 2). ;o)


Picklesworth2006
Isn't this already at Sourceforge (or, if it's the official one, the usual location in "BlitzMax\src\maxide"), or is this a different IDE altogether?

Perhaps the Toolbox would be a more orderly place to put this, even if it is source code.
My use of the code archives is generally to do with handy functions while I trust the Toolbox for things like IDEs :)

Anyhow, thanks!
This is actually a really good IDE by Blitz's standards :P


Code Archives Forum