November 30, 2020, 01:10:28 AM

Author Topic: [bmx] MaxIDE by skidracer [ 1+ years ago ]  (Read 699 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] MaxIDE by skidracer [ 1+ years ago ]
« on: June 29, 2017, 12:28:42 AM »
Title : MaxIDE
Author : skidracer
Posted : 1+ years ago

Description : Requires MaxGUI.

Code :
[code=blitzmax]' 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
            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.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.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) cmd$:+" "+MODOPTIONS
      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=CreateButton(MODOPTIONS,20,y,60,24,sync.window,BUTTON_CHECKBOX)
         If i<2
            SetButtonState sync.options,True
            DisableGadget sync.options
         EndIf
         CreateLabel MODINFO,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
         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 SetButtonState options,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) sync:+","+MODOPTIONS
      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=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=Crea

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal