// Menu.bcpl get "Streams.d" external // Outgoing procedures [ InitParam; DisplayParam; PrintParam; Display; FindActiveParam ] external // incoming procedures [ Hint; CheckInput; GetChar GetFixed; Zero; PutTemplate; CreateDisplayStream; ShowDisplayStream SetLinePos; SetBitPos; GetBitPos; GetScanLinePos; Ws; Puts; EraseBits; SetRmarg ] external // incoming statics [ @Mtable; @PointerTable ] external // Outgoing statics [ @Returns; @Active ] static [ Returns=0; Active=0 ] static [ @Current; @selected = 0 ] //local statics structure str[ length byte; char ↑ 1,255 byte ] manifest [ mouseY = #425; mouseX = #424 ] structure MF: [ MinY word MaxY word MinX word MaxX word Line byte; Inverted byte Routine word ] external lMF static lMF = size MF/16 let DisplayParam(proceedure,line,xposn; numargs nargs) = valof [ let S = Mtable!-1 let save = Current Current = Mtable let EndOfTable = Mtable + lMF*6*Mtable!-2 [ if Current>>MF.Routine eq proceedure then break if Current>>MF.Routine eq 0 then break Current = Current+lMF if Current ge EndOfTable then resultis 0 ] repeat if not Current>>MF.MinY then //ie this is a new entry [ Current>>MF.Line = line Current>>MF.MinY = GetScanLinePos(S,line) Current>>MF.MaxY = GetScanLinePos(S,line+1)-1 Current>>MF.MinX = xposn; Current>>MF.MaxX = xposn Current>>MF.Routine = proceedure ] if not SetLinePos(S,Current>>MF.Line) do [ Ws("*nline posn err. line"); resultis 0 ] if not SetBitPos(S,Current>>MF.MaxX) do [ if not SetBitPos(S,37*16) do [ Ws("*nbit posn err."); resultis 0 ] PutTemplate(S," ") ] //Current>>MF.Inverted = false proceedure(1) if save then [ SetLinePos(S,save>>MF.Line); SetBitPos(S,save>>MF.MaxX) ] let MaxX = Current>>MF.MaxX Current = save resultis MaxX ] and GetScanLinePos(stream,line) = valof [ let DCB = stream>>DS.fdcb let fontheight = 2*(DCB>>DCB.height) let initY = 0 DCB = @#420 until DCB eq stream>>DS.fdcb do [ initY=initY+DCB>>DCB.height; DCB=DCB>>DCB.next ] resultis initY*2 + fontheight*line ] and PrintParam(str,p1,p2,p3,p4) be [ if Active eq true then return let S = Mtable!-1 let Inverted = Current>>MF.Inverted //SetLinePos(S,Current>>MF.Line) //SetBitPos(S,Current>>MF.MaxX) EraseBits(S,Current>>MF.MinX-GetBitPos(S),0); Current>>MF.Inverted = 0 if str>>str.char↑1 ne #40 then Puts(S,#40) PutTemplate(S,str,p1,p2,p3,p4) if str>>str.char↑(str>>str.length) ne #40 then Puts(S,#40) Current>>MF.MaxX = GetBitPos(S) if (Current>>MF.MaxX-Current>>MF.MinX) ls 16 then Current>>MF.MaxX = Current>>MF.MinX + 16 MarkParam(Inverted ne 0) ] and Display(char) be [ Puts(Mtable!-1,char); Current>>MF.MaxX = GetBitPos(Mtable!-1) ] and FindActiveParam() be [ let X = @mouseX; let Y = @mouseY if Current then //see if it is still valid [ if Y gr Current>>MF.MinY & Y ls Current>>MF.MaxY & X gr Current>>MF.MinX & X ls Current>>MF.MaxX then [ Active = true; Returns = Returns+1; Current>>MF.Routine(); return ] ] //if not Button(Left,Depressed) then return MarkParam(false) //un-invert the old parameter Current = 0; Active = false let ptr = Mtable let i = 0 [ i=i+1 if (not ptr>>MF.MinY) % (i eq 6*Mtable!-2) then [ if CheckInput() then GetChar(); return ] //flush out any input & return if Y gr ptr>>MF.MinY & Y ls ptr>>MF.MaxY & X gr ptr>>MF.MinX & X ls ptr>>MF.MaxX then break ptr = ptr+lMF ] repeat Current = ptr; Active = true MarkParam(true) Returns = 0 Current>>MF.Routine(false,Returns) ] and MarkParam(mode) be [ if not Current then return unless mode eq true xor Current>>MF.Inverted then return if mode eq false then Hint(0) let S = Mtable!-1 SetLinePos(S,Current>>MF.Line) SetBitPos(S,Current>>MF.MinX) EraseBits(S,Current>>MF.MaxX-Current>>MF.MinX,-1) Current>>MF.Inverted = mode ] //The following proceedure is used only once during initialization //so it can be copied to an "init" file and discarded here //and InitParam(lines,AboveStream,Font) = valof // [ // let DCB = @#420 // let fontheight = 2*(DCB>>DCB.height)//get height of sysfont // if Font then fontheight = Font!-2 // external CreatDisplayArea // let stream,Mbuff = nil,nil // if AboveStream then // [ // Mbuff = GetFixed(lMF*lines*6+2)+2;Zero(Mbuff,lMF*lines*6) // let DispBuffLength = (38*FontHeight + 6)*lines // let DispBuff = GetFixed(DispBuffLength) // stream = CreateDisplayStream(lines, DispBuff, DispBuffLength, Font, 0, DSstopright+DSstopbottom) // ShowDisplayStream(stream,DSbelow,AboveStream) // let Dstream = CreatDisplayArea(0,2,0,1) // ShowDisplayStream(Dstream,DSabove,stream) // Mbuff!-1 = stream // Mbuff!-2 = lines // ] // stream = Mbuff!-1 // for i=1 to lines do //Send enough char's to fill each line in the stream // [ for c=0 to 120 do Puts(stream,#40) // if i ne lines do Puts(stream,$*n) // ] // SetLinePos(stream,0) // Current = 0 // resultis Mbuff // ]