; ; PROGRAM: MENU ; AUTHOR: RICHARD CONN ; VERSION: 3.2 ; DATE: 10 June 84 ; PREVIOUS VERSIONS: 3.1 (28 Mar 84), 3.0 (18 Mar 84) ; DERIVATION. MENU 1.4 for ZCPR2 ; VERS EQU 32 ; ; MENU is the ZCPR3 Menu Processor. It loads, looks for the MENU.MNU ; file, and then displays it to the user (optionally) and prompts him for ; a single-character command. The ZCPR3 Multiple Command Line Buffer must ; be installed for MENU to work, and MENU uses this buffer to chain to the ; programs selected by the user and return to itself at the proper place. ; ; MENU supports multiple menus within one MENU.MNU file. When a command ; is invoked, MENU returns to the menu the command came from. ; ; MENU will ONLY RUN on ZCPR3 systems with the Multiple Command Line ; Buffer Option enabled. ; ; ; Menu Constants ; sysmenu equ 0 ;System Menu Enabled? 0=no, 1=yes ; 1 Special Menu Command Chars RNM EQU '>' ;NEXT MENU RNMP EQU '.' ;NEXT MENU PRIME (ALTERNATE) RLM EQU '<' ;LAST MENU RLMP EQU ',' ;LAST MENU PRIME (ALTERNATE) RFM EQU '*' ;FIRST MENU ; if sysmenu RSM EQU '$' ;SYSTEM MENU (PASSWORD REQUIRED) ; THIS IS SAME AS CONTROL CHAR endif ;sysmenu ; 2 Internal Menu Control Chars MCMD EQU ':' ;COMMAND TO JUMP TO ANOTHER MENU PCHAR EQU '"' ;INDICATES AUTO PROMPT FOR SPECIFIC CMD MINDIC EQU '#' ;MENU SECTION INDICATOR MFIRST EQU '%' ;FIRST MENU INDICATOR GOPTION EQU '-' ;GLOBAL OPTION INDICATOR WOPTION EQU '!' ;ACTIVATES WAIT UPON RETURN ; 3 Menu Option Chars COPTION EQU 'C' ;DISPLAY COMMAND LINE TO USER DOPTION EQU 'D' ;DISPLAY MENU TO USER POPTION EQU 'P' ;PAGE OUT MENU DISPLAY TO USER XOPTION EQU 'X' ;DISABLE ZCPR3 RETURN ; 4 Miscellaneous IBUFSZ EQU 254 ;SIZE OF INPUT LINE BUFFER VARFLAG EQU '$' ;VARIABLE FLAG ;(FOLLOWED BY D,U,Fn,Nn,Tn) CMDSEP EQU ';' ;ZCPR3 COMMAND SEPARATOR ; ; Enter/Exit Standout Mode (Recommended that these values not be changed) ; DIM EQU 'A'-'@' ; ^A TO ENTER STANDOUT NOTDIM EQU 'B'-'@' ; ^B TO EXIT STANDOUT ; ; MACRO Library of Definitions ; MACLIB Z3BASE.LIB ; ; ZCPR3 CONSTANTS ; wboot equ 0 bentry equ 5 fcb equ 5ch tbuff equ 80h BEL equ 7 CR equ 0dh LF equ 0ah CTRLC equ 'C'-'@' TAB equ 'I'-'@' CTRLZ equ 'Z'-'@' ; ; MACROS TO PROVIDE Z80 EXTENSIONS ; MACROS INCLUDE: ; ; BR - JUMP RELATIVE ; BRC - JUMP RELATIVE IF CARRY ; BRNC - JUMP RELATIVE IF NO CARRY ; BRZ - JUMP RELATIVE IF ZERO ; BRNZ - JUMP RELATIVE IF NO ZERO ; BJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO ; PUTRG - SAVE REGISTERS ; GETRG - RESTORE REGISTERS ; ; ; ; Z80 MACRO EXTENSIONS ; BR MACRO ?N ;;JUMP RELATIVE IF I8080 ;;8080/8085 JMP ?N ELSE ;;Z80 .Z80 JR ?N .8080 ENDIF ;;I8080 ENDM ; BRC MACRO ?N ;;JUMP RELATIVE ON CARRY IF I8080 ;;8080/8085 JC ?N ELSE ;;Z80 .Z80 JR C,?N .8080 ENDIF ;;I8080 ENDM ; BRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY IF I8080 ;;8080/8085 JNC ?N ELSE ;;Z80 .Z80 JR NC,?N .8080 ENDIF ;;I8080 ENDM ; BRZ MACRO ?N ;;JUMP RELATIVE ON ZERO IF I8080 ;;8080/8085 JZ ?N ELSE ;;Z80 .Z80 JR Z,?N .8080 ENDIF ;;I8080 ENDM ; BRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO IF I8080 ;;8080/8085 JNZ ?N ELSE ;;Z80 .Z80 JR NZ,?N .8080 ENDIF ;;I8080 ENDM ; BJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO IF I8080 ;;8080/8085 DCR B JNZ ?N ELSE ;;Z80 .Z80 DJNZ ?N .8080 ENDIF ;;I8080 ENDM ; PUTRG MACRO PUSH H ;;SAVE REGISTERS IN ORDER PUSH D PUSH B ENDM ; GETRG MACRO POP B ;;RESTORE REGISTERS IN ORDER POP D POP H ENDM ; ; END OF Z80 MACRO EXTENSIONS ; ; ; Externals from SYSLIB ; ext z3vinit,cls,stndout,stndend ext getcl1,putcl,getsh2,qshell,retud,getefcb,shpush,shpop ext getshm,putshm,moveb,getfn2,pfn1,getcrt,getzrun,putzex,putcst ext eprint,cin,cout,caps,crlf,pafdc,madc,bline,initfcb,sksp ext f$open,f$close,f$read,codend,hmovb ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3vinit ;initialize the ZCPR3 Env and the VLIB Env jmp strt ; ; This is the FCB which defines the default name of the MENU.MNU file ; if sysmenu ppass: db 'SYSTEM ',0 ;system password endif ;sysmenu ; menufcb: db 0 ;FCB for MENU.MNU db 'MENU ' db 'MNU' ds 4 scratch: ;this doubles as a scratch area ds 16 ;buffer definition is at end of program ds 4 ;36 bytes total ; ; Start of Program ; strt: ; ; Check for Shell Stack ; call getsh2 ;get shell status brnz strt0 ;skip over shell init call eprint db ' No Shell Stack',0 ret ; ; See if Command Line Available ; strt0: call getcl1 ;get line brnz strt01 call eprint db ' No Command Line',0 ret ; ; See if this program was invoked as a shell ; strt01: call qshell ;find out from ZCPR3 environment push psw ;save status xra a ;A=0 call putcst ;put command status (normal = 0) pop psw ;restore status jz menu ;do not push onto stack if invoked as a shell ; ; Set Name of Shell from External FCB if Possible or From Default if Not ; setshn: call retud ;get run address lxi h,shdisk ;pt to shell disk mov a,b ;get disk adi 'A' ;convert to letter mov m,a ;set disk letter inx h ;pt to user 10's mov a,c ;get user number mvi b,10 ;subtract 10's mvi d,'0' ;set char setshn1: sub b ;subtract brc setshn2 inr d ;increment digit br setshn1 setshn2: add b ;get 1's mov m,d ;set 10's digit for user inx h ;pt to 1's digit adi '0' ;compute 1's digit mov m,a ;set 1's digit call getefcb ;get ptr to external fcb brz strt02 ;no external FCB, so use default name inx h ;pt to program name lxi d,shname ;pt to string mvi b,8 ;8 chars call moveb ;copy into buffer ; ; Check for File Name and Set It If Given ; strt02: lxi h,fcb+1 ;pt to file name lxi d,menufcb+1 mvi b,11 ;11 chars mov a,m ;get first char cpi ' ' cnz moveb ;copy if one present ; ; Set File Name in MENUFCB into Line ; lxi h,menufcb+1 ;set shell file name lxi d,shfile ;pt to shell file mvi b,8 ;8 chars strt03: mov a,m ;get next char cpi ' ' ;done? brz strt04 stax d ;put char inx d ;pt to next strt04: inx h ;pt to next bjnz strt03 mvi a,'.' ;put dot stax d inx d ;pt to next mvi b,3 ;file type strt05: mov a,m ;copy stax d inx h ;pt to next inx d bjnz strt05 xra a ;store zero stax d ; ; Set Menu Number ; mvi b,1 ;shell message 1 xra a ;menu 0 call putshm ;set message ; ; Push Name of Shell onto Stack ; lxi h,shdisk ;pt to name of shell call shpush ;push shell onto stack brnz strt2 ; ; Shell Successfully Installed ; call eprint db ' Shell Installed',0 ret ; ; Shell Stack Push Error ; strt2: cpi 2 ;shell stack full? brnz strt3 ; ; Shell Stack is Full ; call eprint db ' Shell Stack Full',0 ret ; ; Shell Stack Entry Size is too small for command line ; strt3: call eprint db ' Shell Stack Entry Size',0 ret ; ; Check for ZEX Execution and Pass ZEX if So ; menu: call getzrun ;is ZEX running? brz runmenu ;process menu if not br menuz1 ;skip new line menuzex: call crlf ;new line menuz1: call eprint db 'Menu> ',0 mvi a,1 ;tell ZEX that it is prompted call putzex call codend ;set up buffer mvi m,ibufsz ;set size mvi a,0FFH ;capitalize call bline ;get line from ZEX xra a ;A=0 call putzex ;resume ZEX normally call sksp ;skip over leading spaces mov a,m ;check for comment cpi ';' brz menuzex xchg ;DE pts to command line xra a ;don't display command sta cpflag jmp runcmnd ;run command pted to by DE ; ; Begin Menu Processing ; runmenu: call eprint db 'MENU Version ' db (vers/10)+'0','.',(vers mod 10)+'0',0 ; ; Check for Wait Flag and Wait if So ; mvi b,0 ;get shell message 0 call getshm ani 80h ;check for wait flag cnz sak ;Strike Any Key ; ; Open Menu File ; lxi h,fcb ;copy FCB into MENU FCB lxi d,menufcb mvi b,36 ;36 bytes push d ;save ptr call moveb pop d ;pt to MENU.MNU FCB call initfcb ;init fcb call f$open ;open file brz menu1 ;abort if no menu call eprint db CR,LF,' File ',0 lxi d,menufcb+1 call pfn1 call eprint db ' Not Found',0 jmp shpop ; ; Load MENU.MNU from disk ; menu1: call codend ;get address of buffer for menu load mload: lxi d,menufcb ;pt to FCB call f$read ;read in next block ora a ;error? brnz mloaddn ;load done if error lxi d,tbuff ;copy from TBUFF into memory pted to by HL xchg ;HL is source, DE is dest mvi b,128 ;128 bytes call hmovb lhld bentry+1 ;get address of top of TPA mov a,h ;set to bottom of ZCPR3 sui 10 cmp d ;about to overflow ZCPR3? brnc mload1 ;continue if not call eprint db CR,LF,' TPA Full',0 ret mload1: xchg ;HL pts to next byte to load to br mload ;continue load ; ; Init Flags and Clear MSB of all bytes in Menu File ; mloaddn: call f$close ;close input file mvi m,CTRLZ ;ensure EOF mark lxi d,80H ;pt to next block dad d shld ibuff ;set ptr to input line buffer mvi m,ibufsz ;set size dad d ;allow 256 bytes dad d shld expline ;set ptr to expand line xra a ;A=0 sta cflag ;turn off command display sta dflag ;turn off menu display sta pflag ;disallow paging sta cpmok ;turn off ZCPR3 return flag call codend ;pt to beginning of file push h ;save ptr menul1: mov a,m ;get byte ani 7FH ;mask out MSB mov m,a ;put byte inx h ;pt to next cpi CTRLZ ;EOF? brnz menul1 ;continue if not ; ; Mark all Menu Sections ; pop h ;HL pts to first byte of menu mvi b,0FFH ;set menu counter ; ; Skip to Next Menu ; menul2: mov a,m ;get byte cpi CTRLZ ;error? jz mstrerr ;structure error if so cpi MINDIC ;menu indicator (start of menu?) brnz menul4 ori 80H ;beginning of menu found -- set MSB mov m,a ;put byte inr b ;increment menu count inx h ;pt to next mov a,m ;get byte cpi MINDIC ;menu indicator (end of menu?) brz menul5 ;done if so cpi CTRLZ ;error? jz mstrerr ; if sysmenu cpi RSM ;system menu indicator? brnz menul3 mov a,b ;set system menu number sta smeno mvi a,0FFH ;set flag sta smenfl ;system menu present dcx h ;back up to beginning of menu shld smenadr ;start address inx h ;pt to RSM endif ;sysmenu ; ; Skip out Menu Display ; menul3: call lskipt ;skip to beginning of next line brz menul4 ;found menu indicator cpi CTRLZ ;error? jz mstrerr br menul3 ;continue if not ; ; Skip to Next Menu ; menul4: call lskip ;skip to beginning of next menu br menul2 ; ; Check Menu Options ; menul5: call codend ;pt to beginning of file mov a,m ;check for option cpi GOPTION ;global option char? jnz mfile ;if no global option, scan for menu files inx h ;pt to option char option: mov a,m ;get option char call caps ;capitalize inx h ;pt to next cpi CR ;done? brz optdn cpi COPTION ;display command? brz optc cpi DOPTION ;display menu? brz optd cpi POPTION ;paging? brz optp cpi XOPTION ;exit OK? jnz mstrerr ;option error if not ; ; Disable Exit to ZCPR3 ; mvi a,0FFH ;turn flag off sta cpmok br option ; ; Process Paging Option ; optp: mvi a,0FFH ;set flag sta pflag br option ; ; Process Display Menu Option ; optd: mvi a,0FFH ;set flag sta dflag br option ; ; Process Display Command Option ; optc: mvi a,0FFH ;set flag sta cflag br option ; ; Option Processing Done ; optdn: inx h ;skip LF ; ; Check for Menu Display ; mfile: mov a,m ;get first byte ani 7FH ;mask cpi MINDIC ;start of menu? jnz mstrerr ; ; Check and Set First Menu ; shld mstart ;save start address of first menu item mvi m,MFIRST+80H ;set first char of first menu ; ; Entry Point for Menu Display ; On entry, HL pts to first byte of current menu ; dmenu: mvi b,1 ;shell message 1 contains menu number call getshm ;get menu number flag cnz mchc0 ;skip to proper menu shld cstart ;save start address of current menu lda cflag ;copy display command flag for temp use sta cpflag lda dflag ;copy display menu flag for temp use sta dpflag lda pflag ;copy paging flag for temp use sta ppflag inx h ;pt to first char after menu indicator char dispm1: mov a,m ;get char call caps ;capitalize inx h ;pt to next cpi CR ;end of options? brz dispm2 ; if sysmenu cpi RSM ;system menu? brz dispm1 ;ok if so endif ;sysmenu ; cpi COPTION ;command display? brz dispmc cpi DOPTION ;display? brz dispmd cpi POPTION ;paging? brz dispmp cpi XOPTION ;ZCPR3 return? jnz mstrerr ;error if not ; ; Toggle ZCPR3 Return Option ; lda cpmok ;get flag cma ;toggle sta cpmok br dispm1 ; ; Toggle Paging Option ; dispmp: lda ppflag ;get flag cma ;toggle sta ppflag br dispm1 ; ; Toggle Display Menu Option ; dispmd: lda dpflag ;get flag cma ;toggle sta dpflag br dispm1 ; ; Toggle Display Command Option ; dispmc: lda cpflag ;get flag cma ;toggle sta cpflag br dispm1 ; ; Done with Menu-Specific Option Processing ; dispm2: call lskip ;skip to LF lda dpflag ;display menu? ora a ;0=no brz dispm8 ;skip over menu if not call getnlines ;get line count in A sta pagcnt ;set count lda ppflag ;paging? ora a ;0=no push psw ;save flag cnz cls ;clear screen if so pop psw ;get flag cz crlf ;else new line ; ; Print Next Line of Menu if not Starting with ESCAPE Char (MINDIC) ; dispm3: mov a,m ;get first char of line ani 7FH ;mask cpi MINDIC ;done? brz dispm4 call expand ;expand line pted to by HL push h ;save ptr to next line xchg ;HL pts to expanded line call lprintx ;print line pted to by HL ending in pop h ;pt to next line br dispm3 ; ; Done with Menu Display -- Page it out ; dispm4: call lskip ;skip to first char of next line (option char) shld optstrt ;set start address of options lda pagcnt ;number of remaining lines mov b,a ;count in B ora a ;ok? brz dispm6 ;don't do anything if already there lda ppflag ;page? ora a ;0=No brz dispm6 ; ; Page Loop for Menu Display ; dispm5: call crlf ;new line bjnz dispm5 ; ; Determine if Another Menu Follows ; dispm6: xra a ;A=0 sta nmenfl ;set for no next menu mov a,m ;ok? ani 7FH ;mask cpi CTRLZ ;error if EOF jz mstrerr cpi MINDIC ;next menu? brnz dispm7 inx h ;double indicator if end mov a,m cpi MINDIC ;end? brz dispm9 ; if sysmenu cpi RSM ;system menu = no next menu brz dispm9 endif ;sysmenu ; mvi a,0FFH ;set next menu sta nmenfl br dispm9 dispm7: call lskip ;skip to next line br dispm6 ; ; Skip over current menu so it is not displayed ; dispm8: call lskipt ;skip to beginning of command brnz dispm8 call lskip ;skip over end of display indicator shld optstrt ;set pointer to options br dispm6 ;determine if next menu available dispm9: ; ; Ready for Option Input ; The following Flags/Values are now set: ; CPFLAG -- Display Command Flag (0=No, 0FFH=Yes) ; DPFLAG -- Display Menu Flag (0=No, 0FFH=Yes) ; OPTSTRT -- Address of First Menu Option ; NMENFL -- 0 if no next menu, 0FFH if next menu ; MSTART -- Start Address of MINDIC Before Menu Display ; (MSTART)=MFIRST with MSB Set prompt: call stndout ;begin standout mvi a,0ffh sta pagcnt ;turn off paging sta dpflag ;turn on future menu displays call retud ;get DU mov a,b ;print D adi 'A' call cout mov a,c ;print U call pafdc call eprint db '> Command (CR=Menu',0 lda cpmok ;OK to return to ZCPR3? ora a ;0=No cnz prmptc lhld cstart ;pt to first char mov a,m ;get it ani 7FH ;mask cpi MFIRST cnz prmptf ;print previous menu prompt if not first menu lda nmenfl ;next menu available? ora a ;0=No cnz prmptn ;print next menu prompt call eprint db ') - ',0 call stndend ;end standout prompt1: call cin ;get response call caps ;capitalize mov b,a ;result in B ; ; Check for CR ; cpi CR ;? jz dispm2 ;reprint menu if so ; ; Check for Reboot ; lda cpmok ;ok to abort? ora a ;0=No brz prmpt0 mov a,b ;get command cpi CTRLC ;reboot? jz shpop ;pop shell stack and return to OS if so ; ; Check for Command to Return to First Menu ; prmpt0: mov a,m ;get it ani 7FH ;mask cpi MFIRST brz prmpt1 mov a,b ;get command cpi RFM ;return to first menu? brnz prmpt1 lhld mstart ;pt to first menu mvi b,1 ;shell message 1 is menu number xra a ;A=0=menu 0 jmp putshm ;reenter shell at first menu ; ; Check for Command to go to Next Menu ; prmpt1: lda nmenfl ;next menu available? ora a ;0=No brz prmpt2 mov a,b ;get command cpi RNMP ;goto next menu? brz rnmx cpi RNM ;goto next menu? brnz prmpt2 rnmx: mvi b,1 ;shell message 1 is menu number call getshm ;increment menu number inr a jmp putshm ;reenter menu system at new menu ; ; Check for Command to go to Last Menu ; prmpt2: mov a,m ;get menu char ani 7FH ;at first menu? cpi MFIRST brz prmpt3 ;skip if at first menu mov a,b ;get command cpi RLMP ;goto last menu? brz lstmnu cpi RLM ;goto last menu? brnz prmpt3 lstmnu: mvi b,1 ;shell message 1 is menu number call getshm ;decrement menu number dcr a jmp putshm ;reenter shell at last menu ; ; Check for Command to goto System Menu ; prmpt3: if sysmenu ; lda smenfl ;system menu available? ora a ;0=No brz prmpt4 mov a,b ;get command cpi RSM ;system menu? brnz prmpt4 call password ;prompt for and get password jnz prompt ;reprompt if error lhld smenadr ;get address of system menu lda smeno ;set system menu number mvi b,1 ;shell message 1 is menu number jmp putshm ;reenter shell at system menu ; endif ;sysmenu ; ; This is where additional functions may be added ; prmpt4: ; ; Check for Option Letter ; lhld optstrt ;pt to first option char prmptx: mov a,m ;get it call caps ;capitalize cpi MINDIC ;at next menu? brz prmpter cmp b ;match user selection? brz prmptd call lskip ;skip to next line br prmptx ; ; Invalid Option ; prmpter: call eprint db BEL,0 jmp prompt1 ; ; Process Option ; prmptd: mov a,b ;output user selection call cout mvi b,0 ;shell message 0, bit 7 = wait flag call getshm ani 7FH ;set no wait call putshm inx h ;pt to first letter of command mov a,m ;get it cpi MCMD ;invoke other menu? jz mchcmd ;menu change command cpi WOPTION ;turn on wait? brnz prmptg mvi b,0 ;shell message 0, bit 7 = wait flag call getshm ori 80h ;set wait flag call putshm ;set shell message inx h ;skip option char prmptg: call expand ;expand line, DE pts to result ; ; Run Command Pted to by DE ; runcmnd: call getcl1 ;get address of command buffer mov b,h ;... in BC also mov c,l mvi a,4 ;HL=HL+4 for address of first char add l mov l,a mov a,h aci 0 mov h,a mov a,l ;store address stax b inx b mov a,h stax b ; ; Copy Command Line in DE into Buffer in HL ; cmdcpy: ldax d ;get command letter call caps ;capitalize it ora a ;done? brz ccpyd cpi CR ;done? brz ccpyd cpi PCHAR ;prompt? brz ccpyp mov m,a ;store it inx h ;pt to next inx d br cmdcpy ccpyd: mvi m,0 ;store ending 0 jmp cmddisp ;optionally display command ; ; Prompt User for Input and Accept It ; ccpyp: inx d ;pt to first char of prompt call crlf ;new line ccpyp1: ldax d ;get char cpi PCHAR ;end of prompt? brz ccpyp2 cpi CR ;new line? brz ccpyp3 call cout ;echo char inx d ;pt to next char br ccpyp1 ;continue looping ccpyp2: inx d ;pt to char after closing PCHAR ccpyp3: push d ;save ptr to next char xchg ;DE pts to buffer mvi a,0FFH ;capitalize input from user lhld ibuff ;input line buffer call bline ;get input from user xchg ;HL pts to buffer, DE pts to user input cmdlp: ldax d ;get char from user ora a ;end of input? brz cmdlp1 ;store rest of line mov m,a ;store char inx h ;pt to next inx d br cmdlp cmdlp1: pop d ;DE pts to next char, HL pts to buffer br cmdcpy ;resume copying ; ; Check for Display of Loaded Command and Do So if Set ; cmddisp: lda cpflag ;display command? ora a ;0=No rz ;return to OS if so to run command call crlf ;new line call getcl1 ;pt to first char mov e,m ;get low-order address inx h mov d,m ;get high-order address xchg ;HL pts to first char cmdd1: mov a,m ;get char cpi CMDSEP ;done if command separator rz inx h ;pt to next call cout ;print char br cmdd1 ; ; Menu Change Command -- Jump to Specified Menu ; mchcmd: inx h ;pt to menu number call eval ;convert to decimal number in A sta menuno ;save menu number call mchc0 ;skip to desired menu to check for it lda menuno ;get menu number mvi b,1 ;menu number is shell message 1 jmp putshm ;set message and reenter shell ; ; Entry Point if MENU is Reinvoked ; mchc0: mov b,a ;menu number in B inr b ;add 1 for initial offset lhld mstart ;pt to first menu mchc1: dcr b ;count down rz ;done if found mchc2: call lskipt ;skip to next line brnz mchc2 ;continue if not end of menu display mchc3: call lskipt ;skip to next line brnz mchc3 ;continue if not at end of menu commands inx h ;end of MENU.MNU? mov a,m ;yes if double MINDIC ani 7FH ;mask cpi MINDIC brz mchcerr ;error if so dcx h ;pt to first char br mchc1 ;continue ; ; Premature End of Menu File ; mchcerr: pop psw ;clear stack jmp mstrerr ;menu structure error ; ; Print Line pted to by HL Ending in ; Decrement PAGCNT ; lprintx: call lprint ;print without jmp crlf ;do ; ; Print Line Pted to by HL; Decrement PAGCNT ; lprint: mvi b,0 ;set tab counter lprnt0: mov a,m ;get char inx h ;pt to next ani 7FH ;mask MSB cpi DIM ;goto standout mode? brz lprnt3 cpi NOTDIM ;end standout mode? brz lprnt4 cpi TAB ;tabulate? brz lprnt2 cpi CR ;done? brz lprnt1 call cout ;print inr b ;incr tab counter br lprnt0 lprnt1: inx h ;pt to first char of next line lda pagcnt ;count down pages dcr a sta pagcnt rnz call getnlines ;get line count in A sta pagcnt call eprint db CR,LF,'Pause -',0 br sak1 lprnt2: mvi a,' ' ;print call cout inr b ;incr tab counter mov a,b ;done? ani 7 ;every 8 brnz lprnt2 br lprnt0 lprnt3: call stndout ;enter standout mode br lprnt0 lprnt4: call stndend ;end standout mode br lprnt0 ; ; Strike Any Key Message ; sak: mvi b,0 ;clear any pending wait call getshm ani 7FH ;mask MSB call putshm sak1: call stndout ;goto standout call eprint db ' Strike Any Key - ',0 call stndend ;exit standout call cin ;get response call crlf ;new line ret ; ; Prompt for, input, and check password (only one chance) ; If accepted, return with Zero Flag Set; if not, return with NZ ; if sysmenu password: call eprint db CR,LF,'Pass? ',0 lhld ibuff ;pt to input line buffer xra a ;don't capitalize user input call bline ;get line from user lxi d,ppass ;pt to system password pass1: ldax d ;get sys pass char cmp m ;ok? brnz passerr ;error if no match inx h ;pt to next inx d ora a ;end of strings? brnz pass1 ret ;return with zero set to show match passerr: call eprint db CR,LF,' Password Error',0 call sak1 ;strike any key call crlf mvi a,0FFH ;set no zero ora a ret endif ;sysmenu ; ; Skip to Beginning of Next Line and Test First Char for Menu Indicator ; lskipt: call lskip ;skip mov a,m ;get char ani 7FH ;mask cpi MINDIC ;test ret ; ; Skip to Beginning of Next Line ; lskip: mov a,m ;get char ani 7FH ;mask out MSB inx h ;pt to next cpi LF brnz lskip ret ; ; Print ZCPR3 Return Prompt ; prmptc: call eprint db ', ^C=Z3',0 ret ; ; Print First/Last Menu Chars ; prmptf: call eprint db ', ',RFM,'=1st Menu, ',RLM,'=Prev Menu',0 ret ; ; Print next menu message ; prmptn: call eprint db ', ',RNM,'=Next Menu',0 ret ; ; Menu Structure Error -- FATAL ; This message is printed to indicate an error in the structure of ; the MENU.MNU file. ; mstrerr: call eprint db CR,LF,' Structure Error',0 jmp shpop ; ; Expand Line Pted to by HL into Scratch Area ; Return with HL pting to next line, DE pting to current line ; expand: xchg lhld expline ;pt to buffer xchg exp1: mov a,m ;get next char ani 7fh ;mask MSB stax d ;store char cpi CR ;end of line? jz expx inx h ;pt to next inx d cpi VARFLAG ;variable follows? brnz exp1 ; ; Variable Identified - Process it ; mov a,m ;get next char inx h ;pt to next cpi VARFLAG ;one variable char? brz exp1 ;resume if double VARFLAG dcx d ;pt to variable position call caps ;capitalize variable cpi 'D' ;current disk? brz expdisk cpi 'U' ;current user? brz expuser cpi 'F' ;filename.typ? brz expfile cpi 'N' ;filename? brz expname cpi 'T' ;filetype? brz exptype br exp1 ;resume expansion ; ; Expand Exit ; expx: inx h ;pt to line feed mov a,m ;get it cpi LF ;line feed? brnz expx1 inx h ;pt to char after line feed expx1: xchg ;DE pts to next line lhld expline ;pt to expanded line xchg ;HL pts to next line, DE pts to expanded line ret ; ; Expand Disk ; expdisk: call retud ;get disk in B mov a,b ;get disk number (A=0) adi 'A' ;convert to ASCII stax d ;store letter inx d ;pt to next br exp1 ;resume expansion ; ; Expand User ; expuser: call retud ;get user in C mov a,c ;get user number mvi b,10 ;subtract 10's mvi c,'0' ;set char expu1: sub b ;-10 brc expu2 inr c ;increment digit br expu1 expu2: add b ;+10 adi '0' ;convert 1's to ASCII mov b,a ;B=1's mov a,c ;get 10's stax d ;store 10's inx d mov a,b ;get 1's stax d ;store 1's inx d ;pt to next br exp1 ;resume ; ; Expand File ; expfile: call getfnum ;get file number jz exp1 ;resume if error push h ;save ptr to next char call ptfn ;set ptr to file name call putn ;put file name mvi a,'.' stax d ;store dot inx d ;pt to next call putt ;put file type pop h ;restore ptr jmp exp1 ;resume ; ; Expand Name ; expname: call getfnum ;get file number jz exp1 ;resume if error push h ;save ptr to next char call ptfn ;set ptr to file name call putn ;put file name pop h ;restore ptr jmp exp1 ;resume ; ; Expand Type ; exptype: call getfnum ;get file number jz exp1 ;resume if error push h ;save ptr to next char call ptfn ;set ptr to file name mvi a,8 ;add 8 add l mov l,a mov a,h aci 0 mov h,a call putt ;put file type pop h jmp exp1 ;resume ; ; Pt to File Name whose Number (1-4) is in A ; ptfn: mov b,a ;get number in B call getfn2 ;pt to file name 2 push d ;save DE mov a,b ;file 0? ora a brz ptfnx lxi d,11 ;size of file name and type ptfn1: dad d ;pt to next bjnz ptfn1 ptfnx: pop d ;restore DE ret ; ; Put File Name pted to by HL ; putn: mvi b,8 ;8 chars br putc ; ; Put File Type pted to by HL ; putt: mvi b,3 ;3 chars ; ; Copy Chars from HL to DE for up to B bytes -- flush if space ; putc: mov a,m ;get next char cpi ' ' ;skip spaces brz putc1 stax d ;put next char inx d ;pt to next putc1: inx h ;pt to next bjnz putc ret ; ; Get File Number (1 to 4) ; If valid number, return with value in A and HL pting to next char ; If not valid, return with Z and HL pting to last char (F, N, T) ; getfnum: mov a,m ;get char sui '1' ;convert brc getfne ;error cpi 4 ;range? brnc getfne inx h ;pt to next char ret ;NZ from CPI 4 getfne: dcx h ;error return xra a ret ; ; Return Number of Lines on CRT in A ; getnlines: push h ;save HL call getcrt ;get CRT info inx h ;pt to number of lines mov a,m ;get count pop h ;restore HL dcr a ;subtract 1 for footer ret ; ; Convert char string pted to by HL into decimal number in A ; On Entry, HL pts to first digit char ; On Exit, HL pts to after last digit char and A=number ; eval: push b ;save BC mvi b,0 ;set value eval1: mov a,m ;get digit sui '0' ;convert to binary brc eval2 cpi 10 ;range? brnc eval2 inx h ;pt to next digit mov c,a ;new digit in C mov a,b ;multiply B by 10 add a ;*2 add a ;*4 add b ;*5 add a ;*10 add c ;add in new digit mov b,a ;result in B br eval1 eval2: mov a,b ;result in A pop b ;restore ptr ret ; ; These buffers overlay the scratch area to save space ; optstrt equ scratch ;Address of First Option in Current Menu mstart equ optstrt+2 ;Address of First Menu cstart equ mstart+2 ;Address of Current Menu smenfl equ cstart+2 ;System Menu Available Flag (0=No) smeno equ smenfl+1 ;System Menu Number smenadr equ smeno+1 ;Address of First Byte of System Menu nmenfl equ smenadr+2 ;Next Menu Available Flag (0=No) menuno equ nmenfl+1 ;Number of Menu pagcnt equ menuno+1 ;Paging Counter cflag equ pagcnt+1 ;Display Command Line Flag dflag equ cflag+1 ;Display Menu Flag pflag equ dflag+1 ;Paging Flag ; ; Buffers ; ibuff: ds 2 ;input line buffer expline: ds 2 ;scratch area to expand lines in cpflag: ds 1 ;Temp Display Command Line Flag dpflag: ds 1 ;Temp Display Menu Flag ppflag: ds 1 ;Temp Paging Flag cpmok: ds 1 ;OK to Return to ZCPR3 (0=No) tnum: ds 41 ;space for chars and ending 0 shdisk: db 'A' ;disk to return to db '00' ;user to return to db ':;' ;log in and next command shname: db 'MENU ' ;program name (filled in at installation) shfile: ds 13 ;file name (12) and ending 0 end