{ 12/10/87 14:02 Menus} ! The built-in function Set Up Menu expects the data to be given to it ! as an array of records of format dataf. ! Each Value is expected to be a list of lines. %include "sm:consts.inc" %include "sm:formats.inc" %include "sm:utils.inc" %include "sm:smvti.inc" %recordformat dataf(%string(19) name,%record(line80listf) val) %recordformat menuf(%integer item,%string(19) name,%string(63) val) %ownrecord(menuf)%array menu(0:250) %owninteger cursorx,cursory %owninteger datastart=20 %externalstring(31) helpfile="menuhelp" %owninteger linelength=80, menudepth %externalroutinespec view(%string(255) file,topic) %owninteger wdepth=16, wmin, wmax %routinespec write menu %externalroutine screen message(%string(255) s,%string(15) mon) %integer oldout oldout=outstream select output(0) gotoxy(0,wdepth+1) clear line print string(s) %monitor %if mon="mon" %stop %if mon="stop" %or mon="mon" gotoxy(cursorx,cursory-wmin+1) select output(oldout) %end ! If APM. %externalrecord(line80f)%map newline80 %record(line80f) pattern %record(line80f)%name p p==new(pattern) p_next==nil; p_prev==nil p_line="" %result==p %end ! %routine h(%string(31) topic) %string(255) x, y topic=x." ".y %while topic->x.("_").y view(helpfile,topic) %end %externalroutine start screen mode {! If Vax.} { define video(vttype)} ! select input(0); select output(0) set video mode(screen mode+special pad) set frame(wdepth+2,24,0,80) clear frame push window set frame(0,wdepth+1,0,80) clear frame gotoxy(0,0) cursorx=0; cursory=0 prompt("") %end %externalroutine stop screen mode clear frame set video mode(0) %end %externalroutine read screen line(%string(*)%name a) %integer j,k %string(255) u %on %event 15,0 %start read symbol(j) %until j=lf ;! To get rid of residual NL. h(menu(cursory)_name) write menu %finish prompt("") a="" cursorx=datastart gotoxy(cursorx,cursory-wmin+1) clear line %cycle read symbol(j) %exit %if j=lf %or j=enter %signal %event 15,0 %if j='?' screen message("Stopped at ".menu(cursory)_name,"stop") %if j=128+esc %continue %if j<=31 %or j>=128 %if j=del %thenstart ! This supposes that del has not been dealt with at the input. print symbol(sp) k=length(a) k=k-1; cursorx=cursorx-1 k=0 %if k<0; cursorx=datastart %if cursorxlinelength %finish gotoxy(cursorx,cursory-wmin+1) %repeat u=a; lower(u) cursorx=datastart; gotoxy(cursorx,cursory-wmin+1) clear line; print string(a) cursorx=0; gotoxy(cursorx,cursory-wmin+1) %end %externalroutine set up menu(%record(dataf)%arrayname data, %integer mask) %integer flag,i,j %record(line80f)%name p ! Ensure that items 0 and 31 are available for escape. mask=mask!16_80000001 menu(i)=0 %for i=0,1,250 j=0 %for i=0,1,31 %cycle %if mask&1=0 %then flag='n' %else flag='y' mask=mask>>1 %continue %if flag='n' ! Copy wanted item into menu. p==data(i)_val_head %if p==nil %thenstart message("Menu too long","mon") %if j>250 menu(j)_item=i menu(j)_name=data(i)_name %if 0#i#31 %then menu(j)_val="*" %else menu(j)_val="" j=j+1 %finishelsestart %while p##nil %cycle message("Menu too long","mon") %if j>250 menu(j)_item=i menu(j)_name=data(i)_name menu(j)_val=p_line j=j+1 p==p_next %repeat %finish %repeat menudepth=j-1 %end %externalroutine write instruction(%string(255) s) swop window gotoxy(0,wdepth+4) clear line gotoxy(0,wdepth+3) clear line gotoxy(0,wdepth+2) clear line gotoxy(0,wdepth+1) clear line print string(s) swop window gotoxy(cursorx,cursory-wmin+1) %end %routine display line(%integer y) gotoxy(0,y-wmin+1) clear line print symbol(' ') print string(menu(y)_name) gotoxy(datastart,y-wmin+1) print string(menu(y)_val) gotoxy(0,y-wmin+1) %end %routine display item(%integer item,y) gotoxy(0,y-wmin+1) clear line print symbol(' ') print string(menu(item)_name) gotoxy(datastart,y-wmin+1) print string(menu(item)_val) gotoxy(0,y-wmin+1) %end %externalroutine write menu %integer d, i %string(255) s ! Bring position of cursor within menu. %if cursorx<0 %then cursorx=0 %else %c %if cursorx>linelength %then cursorx=linelength %if cursory<0 %then cursory=0 %else %c %if cursory>menudepth %then cursory=menudepth ! Adjust window depth to fit menu. d=wdepth-2 ;! Allow for escape cases. d=menudepth %if d>menudepth ! Adjust window to fit position of cursor. wmin=cursory-d//2; wmin=1 %if wmin<1 wmax=wmin+d; wmax=menudepth-1 %if wmax>menudepth-1 wmin=wmax-d; wmin=1 %if wmin<1 ! Display menu. display item(0,wmin-1) ;! One escape item. display line(i) %for i=wmin,1,wmax display item(menudepth,wmax+1) ;! The other escape item. ! Write instructions. s="Move the cursor to the appropriate line. Press to alter.".snl. %c "Type in the new value and press again. ".snl. %c "For help, type ? and press .".snl. %c "Move the cursor off the screen to see more of the menu." write instruction(s) ! Position cursor. gotoxy(cursorx,cursory-wmin+1) %end %externalintegerfn cursor depth %integer j select input(0) prompt("") gotoxy(0,cursory-wmin+1) %cycle read symbol(j) %exit %if j=lf %if j=down %thenstart cursory=cursory+1 %until cursory>menudepth-1 %or %c menu(cursory)_item#menu(cursory-1)_item %finishelse %c %if j=up %thenstart cursory=cursory-1 %until cursory<1 %or %c menu(cursory)_item#menu(cursory-1)_item %finishelse %c %if j&127=esc %then %signal 15,3 %else %c %if j='?' %thenstart read symbol(j) %until j=lf ;! get rid of residual NL. %if cursory=wmin-1 %then h(menu(0)_name) %else %c %if cursory=wmax+1 %then h(menu(31)_name) %else %c h(menu(cursory)_name) write menu %finish %if cursory<0 %then cursory=0 %else %c %if cursory>menudepth %then cursory=menudepth %if wmin-1<=cursory<=wmax+1 %then gotoxy(0,cursory-wmin+1) %elsestart %if cursory