// Menu.bcpl -- a BCPL package to define menus // on the display screen. // A menu is defined as a collection of "boxes". // A "box" is defined by an "origin" (upper left corner) and // a "corner" (lower right corner). If a bitmap exists // for the box then a dcb is specified and the origin // and corner are given relative to the dcb bitmap. get "MenuDefs.d" external // incoming OS statics and procedures [ sysZone Allocate Zero ] external MenuInitHelp static MenuData=false let ScanMenu(menu,loopOverMenu,returnKey,ignoreSense;numargs na) = valof [ // returns false if nothing selected // returns true if dcb exists but not on the screen // if box was selected returns key in left byte // and position in vector in right byte // default case if (na eq 0) % (menu!0 eq 0) then resultis false if na le 1 then loopOverMenu=true if na le 2 then returnKey=false if na le 3 then ignoreSense=false // define variables let key=(not @#177030) & #377 let box=nil let top,left=nil,nil let Xo,Xc,Yo,Yc=nil,nil,nil,nil // major loop over the menu [ for n=1 to menu!0 do // first word after menu is length [ box=menu!n if (box>>BOX.sensitive ne 0) % ignoreSense then [ if CursorInside(box) then [ key=(not @#177030) & #377 switchon key into [ case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: top=FindDCB(box) if top eq -1 resultis true FlipBox(box) left=top?16*((box>>BOX.dcb)>>DCB.indentation),0 Xo=box>>BOX.xorigin+left Xc=box>>BOX.xcorner+left Yo=box>>BOX.yorigin+top Yc=box>>BOX.ycorner+top if select(Xo,Xc,Yo,Yc,key) resultis n+(returnKey ? (key lshift 8),0) FlipBox(box) ] ] ] ] ] repeatwhile loopOverMenu resultis false ] and ShowMenu() be [ // if data from menu tables is absent go home if MenuData eq 0 then return @#420=MenuData>>DATA.menuDCB ] and CreateMenuDisplayStream(buffer,length,font) = valof ScanMenuDCBChain(buffer,length) and MenuSize() = valof ScanMenuDCBChain() and ScanMenuDCBChain(buffer,length,font;numargs na) = valof [ // go get data from menu tables if MenuData eq 0 then MenuData=MenuInitHelp() let menuDCB=MenuData>>DATA.menuDCB // start work let odd=(buffer&1) buffer=buffer+odd let firstdcb,lastdcb,Size=0,0,0 let dcb=menuDCB while dcb do [ if dcb>>DCB.width then [ if firstdcb eq 0 then firstdcb=dcb lastdcb=dcb ] if na then dcb>>DCB.bitmap=buffer+Size Size=Size+2*(dcb>>DCB.width)*(dcb>>DCB.height) dcb=@dcb ] test na ifso if length le Size resultis false ifnot resultis Size+1 // MenuSize has left by now // still doing CreateMenuDisplayStream if na ls 3 then font=0 let menu=MenuData>>DATA.menu let stringlist=MenuData>>DATA.stringlist for n=1 to menu!0 do ConvertToRelative(menu!n,menuDCB) Zero(buffer,length-odd) for n=1 to menu!0 do [ let bits=(menu!n)>>BOX.bits let flag=(menu!n)>>BOX.flag OutlineBox(menu!n,bits,flag) WriteBox(menu!n,stringlist!n,font) ] // return stream let stream=table [ 0;0 ] stream!0=firstdcb stream!1=lastdcb resultis stream ] and DeleteFromMenu(menu,number) be [ // remove from menu list if menu!0 ls number then return menu!0=menu!0-1 for n=number to menu!0 do menu!n=menu!(n+1) menu!(menu!0+1)=0 ] and WaitUntilPressed(key;numargs na) be [ if (na eq 0) % (key eq 0) then key=#377 while ((not @#177030) & key) eq 0 do loop ] and WaitUntilReleased(key;numargs na) be [ if (na eq 0) % (key eq 0) then key=#377 while ((not @#177030) & key) ne 0 do loop ]