Oops, gets cut off.
part 2:
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