// MenuEditReadWrite.bcpl -- read and write out bcpl files // containing the menu description. get "MenuDefs.d" external // incoming OS procedures [ Ws Wss Wns Gets Puts GetFixed FixedLeft Zero Endofs OpenFile Closes Resets SetBlock MoveBlock Allocate Free FileLength ReadBlock ] external // incoming and outgoing procedures [ ReadFile WriteFile Font getname ReadUserCmItem // from ReadUserCmItem.br ] external // incoming OS statics [ keys dsp ] external // incoming statics [ dcb systemdcb buffer zone menu stringlist boxnames highestname fontPtr ] static // internal statics [ NamesDefault=0 TablesDefault=0 ] structure PTR [ blank word xmin word xmax word height word ] manifest anykey=#377 let WriteFile() be [ // output the manifest file if menu!0 eq 0 then return Ws("*N*N*N*N*N*N") @#420=systemdcb if NamesDefault eq 0 then NamesDefault="MenuNames.d" let name=getname("Manifest file",NamesDefault) if name eq 0 then name=NamesDefault NamesDefault=name let s=OpenFile(name,ksTypeWriteOnly,charItem,verLatestCreate) Wss(s,"// ");Wss(s,name) Wss(s," -- Manifest names for menu windows.*N*N*N") Wss(s,"manifest*N*T[*N") let length=menu!0 for n=1 to length do [ Puts(s,$*T);Wss(s,boxnames!n);Puts(s,$=);Wns(s,n);Puts(s,$*N) ] Wss(s,"*T]*N*N") Closes(s) // output the menu file // ask for name of file Ws("*N") if TablesDefault eq 0 then TablesDefault="MenuTables.bcpl" name=getname("Menu file",TablesDefault) if name eq 0 then name=TablesDefault TablesDefault=name s=OpenFile(name,ksTypeWriteOnly,charItem,verLatestCreate) // start the header Wss(s,"// ");Wss(s,name) Wss(s," -- Tables for setting up menu windows.*N*N*N") Wss(s,"external MenuInitHelp*N*N*N") Wss(s,"let MenuInitHelp() = valof*N*T[") // set up menu table Wss(s,"*N*T// set up menu table*N") Wss(s,"*Tlet menu=table*N*T*T[*N*T*T");Wns(s,length) for n=1 to (length+15)/16 do Wss(s,"*N*T*T0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0") Wss(s,"*N*T*T]*N") for n=1 to length do [ Wss(s,"*Tmenu!");Wns(s,n);Wss(s,"=table [ 0;") Puts(s,$#);Wns(s,menu!n>>BOX.outline,0,8);Puts(s,$;) Wns(s,menu!n>>BOX.xorigin);Puts(s,$;) Wns(s,menu!n>>BOX.yorigin);Puts(s,$;) Wns(s,menu!n>>BOX.xcorner);Puts(s,$;) Wns(s,menu!n>>BOX.ycorner);Puts(s,$;) Puts(s,$#);Wns(s,menu!n>>BOX.controlflags,0,8);Wss(s," ]*N") ] // set up stringlist table Wss(s,"*N*T// set up stringlist table*N") Wss(s,"*Tlet stringlist=table*N*T*T[*N*T*T");Wns(s,length) for n=1 to (length+15)/16 do Wss(s,"*N*T*T0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0") Wss(s,"*N*T*T]*N") for n=1 to length do [ if stringlist!n eq 0 loop Wss(s,"*Tstringlist!");Wns(s,n) Wss(s,"=*"");Wss(s,stringlist!n);Wss(s,"*"*N") ] // set up dcb table let dcbvec=MakeDCBChain() // now write this mess out let ptr=dcbvec+1 Wss(s,"*N*T// set up menuDCB table*N") Wss(s,"*Tlet menuDCB=table*N*T*T[*N*T*T0*N") for n=0 to dcbvec!0-1 do [ if ptr>>DCB.height ne 0 do [ Wss(s,"*T*T0;#");Wns(s,ptr>>DCB.parwd,0,8) Wss(s,";0;");Wns(s,ptr>>DCB.height);Puts(s,$*N) ] ptr=ptr+4 ] Wss(s,"*T*T]*N") Wss(s,"*Ttest (menuDCB&1) eq 1 ifso menuDCB=menuDCB+1*N") Wss(s,"*T*Tifnot for n=0 to ");Wns(s,4*dcbvec!0-1) Wss(s," do menuDCB!n=menuDCB!(n+1)*N") Wss(s,"*Tfor n=0 to ");Wns(s,dcbvec!0-2) Wss(s," do menuDCB!(4**n)=menuDCB+4**(n+1)*N") // now finish up Wss(s,"*N*T// now finish up*N") Wss(s,"*Tlet temp=table [ 0;0;0 ]*N") Wss(s,"*Ttemp!0=menu*N") Wss(s,"*Ttemp!1=stringlist*N") Wss(s,"*Ttemp!2=menuDCB*N") Wss(s,"*Tresultis temp*N*T]*N") Closes(s) ] and MakeDCBChain() = valof [ // first calculate what dcb's are needed // use the buffer space for the screen, will be refreshed later let xmin=buffer let xmax=buffer+808 SetBlock(xmin,800,808) Zero(xmax,808) for n=1 to menu!0 do // scan over the menu [ let box=menu!n let Xo=box>>BOX.xorigin let Xc=box>>BOX.xcorner for m=box>>BOX.yorigin to box>>BOX.ycorner do [ xmin!m=Xo ls xmin!m ? Xo,xmin!m xmax!m=Xc gr xmax!m ? Xc,xmax!m ] ] // make lengths in words to identify tabs and widths for n=0 to 807 do [ if xmin!n gr 606 then xmin!n=0 xmin!n=xmin!n/16 // now equal to tab spacings xmax!n=(xmax!n+15)/16 if xmax!n ge 38 then xmax!n=37 ] // start to set up the dcb's let dcbvec=xmax+808 Zero(dcbvec,4*404+1) let oldflag=xmax!0 ? true,false let flag=0 let ptr=dcbvec+1 for n=0 to 403 do (ptr+4*n)>>PTR.xmin=800 for n=0 to 807 do [ flag=xmax!n ? true,false if (flag ne oldflag) then [ dcbvec!0=dcbvec!0+1 ptr=ptr+4 oldflag=flag ] if xmin!n ls ptr>>PTR.xmin then ptr>>PTR.xmin=xmin!n if xmax!n gr ptr>>PTR.xmax then ptr>>PTR.xmax=xmax!n ptr>>PTR.height=ptr>>PTR.height+1 ] dcbvec!0=dcbvec!0+1 // dcb's have to have even # of lines let ptr=dcbvec+1 for n=0 to dcbvec!0-1 do [ if (ptr>>PTR.height & 1) eq 1 then [ test ptr>>PTR.xmax ifso [ ptr>>PTR.height=ptr>>PTR.height+1 (ptr+4)>>PTR.height=(ptr+4)>>PTR.height-1 ] ifnot [ ptr>>PTR.height=ptr>>PTR.height-1 (ptr+4)>>PTR.height=(ptr+4)>>PTR.height+1 ] ] ptr=ptr+4 ] // scan through for zero height let olddcbvec=dcbvec let oldptr=olddcbvec+1 dcbvec=olddcbvec+(4*410) //still higher in buffer let ptr=dcbvec+1 dcbvec!0=0 for n=0 to olddcbvec!0-1 do [ if oldptr>>PTR.height ne 0 do [ for i = 0 to 3 do [ ptr!i=oldptr!i ] dcbvec!0 = dcbvec!0+1 ptr=ptr+4 ] oldptr=oldptr+4 ] // finish up the dcb chain let ptr=dcbvec+1 for n=0 to dcbvec!0-1 do [ ptr>>PTR.height=ptr>>PTR.height/2 let xmax=ptr>>PTR.xmax let xmin=ptr>>PTR.xmin if xmax then xmax=2*((xmax-xmin)/2+1) if xmax+xmin gr 38 then xmin=xmin-1 ptr>>PTR.xmin=(xmin lshift 8) + xmax // tab, width ptr=ptr+4 ] resultis dcbvec ] and ReadFile() be [ // read the manifest file Ws("*N*N*N*N*N*N") @#420=systemdcb if NamesDefault eq 0 then NamesDefault="MenuNames.d" let s1=nil [ let name=getname("*NManifest file",NamesDefault) if name eq 0 then name=NamesDefault NamesDefault=name s1=OpenFile(name,ksTypeReadOnly,charItem,verLatest) ] repeatuntil s1 // read the menu file // ask for name of file let s2=nil if TablesDefault eq 0 then TablesDefault="MenuTables.bcpl" [ let name=getname("*NMenu file",TablesDefault) if name eq 0 then name=TablesDefault TablesDefault=name s2=OpenFile(name,ksTypeReadOnly,charItem,verLatest) ] repeatuntil s2 // now free up all the space for n=1 to menu!0 do [ if menu!n then Free(zone,menu!n) if stringlist!n then Free(zone,stringlist!n) if boxnames!n then Free(zone,boxnames!n) ] Zero(menu,MaxLength) Zero(stringlist,MaxLength) Zero(boxnames,MaxLength) // now analyze the file // use the buffer space for the screen, will be refreshed later highestname=0 let num=0 let string=buffer let p=0 until p eq $[ do p=Gets(s1) [ p=ReadUserCmItem(s1,string) if p eq $E then break if p eq $P then if equalsSign(string) then [ let c1=findsymbol(string,1,$=) let c2=string>>STRING.length if stringsequal(string,"box") then [ num=getnum(string,4,c1) if num gr highestname then highestname=num ] boxnames!(getnum(string,c1,c2))=getnam(string,1,c1-1) ] ] repeat Closes(s1) // now analyze the file // menu table let menulength=0 until stringsequal(string,"menu!") do ReadUserCmItem(s2,string) while stringsequal(string,"menu!") do [ let c1=findsymbol(string,1,$!) let c2=findsymbol(string,c1,$=) let number=getnum(string,c1,c2) menu!number=Allocate(zone,lBOX) if number gr menulength then menulength=number getmenunumbers(string,menu!number) ReadUserCmItem(s2,string) ] // stringlist table until stringsequal(string,"stringlist!") do [ p=ReadUserCmItem(s2,string) ; if p eq $E break ] while stringsequal(string,"stringlist!") do [ let c1=findsymbol(string,1,$!) let c2=findsymbol(string,1,$=) let c3=findsymbol(string,1,$") let c4=findsymbol(string,c3+1,$") stringlist!(getnum(string,c1,c2))=getnam(string,c3+1,c4-1) ReadUserCmItem(s2,string) ] Closes(s2) // set menu, stringlist and boxnames counters @menu=menulength @stringlist=menulength @boxnames=menulength ] and equalsSign(string) = valof [ for n=1 to string>>STRING.length do [ if string>>STRING.char↑n eq $= then resultis true ] resultis false ] and getnum(string,count1,count2) = valof [ let number=0 let octal=false for n=count1 to count2 do [ let char=string>>STRING.char↑n if char eq $# then octal=true if (char ls $0) % (char gr $9) then loop number=(octal?8,10)*number+char-$0 ] resultis number ] and getnam(string,count1,count2) = valof [ let count=1 let letter=0 let ptr=Allocate(zone,(count2-count1+1)/2+1) for n=count1 to count2 do [ let char=string>>STRING.char↑n letter=letter+1 ptr>>STRING.char↑letter=char ] ptr>>STRING.length=letter resultis ptr ] and getmenunumbers(string,box) be [ let count=findsymbol(string,1,$[) //what does this do? let colon1=findsymbol(string,1,$;) let colon2=findsymbol(string,colon1+1,$;) let colon3=findsymbol(string,colon2+1,$;) let colon4=findsymbol(string,colon3+1,$;) let colon5=findsymbol(string,colon4+1,$;) let colon6=findsymbol(string,colon5+1,$;) box!0=dcb box!1=getnum(string,colon1,colon2) box!2=getnum(string,colon2,colon3) box!3=getnum(string,colon3,colon4) box!4=getnum(string,colon4,colon5) box!5=getnum(string,colon5,colon6) box!6=getnum(string,colon6,string>>STRING.length) ] and findsymbol(string,count,symbol) = valof [ let length=string>>STRING.length until string>>STRING.char↑count eq symbol do count=count+1 resultis count gr length ? length,count ] and stringsequal(string1,string2) = valof [ for n=1 to string2>>STRING.length do [ let char1=string1>>STRING.char↑n let char2=string2>>STRING.char↑n if char1 ne char2 resultis false ] resultis true ] and Font() be [ // read the font file Ws("*N*N*N*N*N*N") @#420=systemdcb let s=nil [ let name=getname("*NFont file",0) if name eq 0 then [ fontPtr=0;return ] s=OpenFile(name,ksTypeReadOnly) ] repeatuntil s // get the length let length=FileLength(s) fontPtr=GetFixed(length) if fontPtr eq 0 then [ Ws("*NNot enough room for font. Only have ") Wns(dsp,FixedLeft()) Ws(" words left. Type any char to continue.") Closes(s) Gets(keys) fontPtr=0 return ] // read the file Resets(s) ReadBlock(s,fontPtr,length) Closes(s) fontPtr=fontPtr+2 ]