#TITLE "TURBODOS 1.4X MENU UTILITY" #PAGE 132,66 MODULE "TDMENU" ; ; +----------------------------------+ ; | MENU UTILITY FOR 16-BIT TURBODOS | ; +----------------------------------+ ; CFUNC == 0XE0 ; C-FUNCTION INTERRUPT TFUNC == 0XDF ; T-FUNCTION INTERRUPT ; LOC Data# ; ; +-----------------------+ ; | TERMINAL CONFIG BLOCK | ; +-----------------------+ ; ESC == 0X1B ; CCURUP:: BYTE 2,ESC,'A',0,0,0,0 ; CURSOR UP CCURDN:: BYTE 2,ESC,'B',0,0,0,0 ; CURSOR DOWN CCURLF:: BYTE 2,ESC,'D',0,0,0,0 ; CURSOR LEFT CCURRT:: BYTE 2,ESC,'C',0,0,0,0 ; CURSOR RIGHT CHOMEC:: BYTE 2,ESC,'H',0,0,0,0 ; HOME CURSOR CURAD1:: BYTE 2,ESC,'F',0,0,0,0 ; CURSOR ADDRESSING STRING 1 CURAD2:: BYTE 0XFF ; FF=R/C, 00=C/R CURAD3:: BYTE 0XFF ; FF=BINARY, 00=ASCII CURAD4:: BYTE ' ' ; BINARY OFFSET CDISON:: BYTE 3,ESC,"-1",0,0,0 ; CURSOR DISPLAY ON CDISOF:: BYTE 3,ESC,"-0",0,0,0 ; CURSOR DISPLAY OFF CLEOLN:: BYTE 2,ESC,'K',0,0,0,0 ; CLEAR TO END OF LINE CLRSCR:: BYTE 2,ESC,'E',0,0,0,0 ; CLEAR SCREEN AND HOME CINHIL:: BYTE 3,ESC,"dA",0,0,0 ; INTO HIGHLIGHTING COTHIL:: BYTE 3,ESC,"d@",0,0,0 ; OUT OF HIGHLIGHTING CINREV:: BYTE 3,ESC,"dP",0,0,0 ; INTO REVERSE COTREV:: BYTE 3,ESC,"d@",0,0,0 ; OUT OF REVERSE CLINES:: BYTE 24 ; NUMBER OF LINES CCOLUM:: BYTE 80 ; NUMBER OF COLUMNS KEYUP:: BYTE 'P'-0X40 ; KEY: CURSOR UP KEYDN:: BYTE 'N'-0X40 ; KEY: CURSOR DOWN KEYXIT:: BYTE 'X'-0X40 ; KEY: EXIT TO O/S NPRIVX:: BYTE 0 ; NONPRIV MAY EXIT IF NZ ; ; +------------------------+ ; | SYSTEM MESSAGE SECTION | ; +------------------------+ ; BANNER:: BYTE "YOUR MENU TITLE HERE$" ; CUSTOMIZABLE MENU HEADER RES 60 ; UP TO 80 CHARS CRLFLF: BYTE "\r\n" CRLF: BYTE "\r\n$" MENTER: BYTE "Enter selection [ ]\8\8$" MINVME: BYTE "\r\n\n\7FATAL ERROR: Menu not " BYTE "terminated or too large!\r\n\n$" TOOMNL: BYTE "\R\N\NTESTING: TOO MANY LINES\R\N\N\N$" SEP: BYTE " = $" PRTC: BYTE "PRESS ANY KEY TO RETURN TO MENU:$" ; ; +----------------------+ ; | DATA STORAGE SECTION | ; +----------------------+ ; NMBLNS: WORD 0 ; NUMBER OF MENU LINES PRIV: BYTE 0 ; PRIVILEGE FLAG ; CMDLN: BYTE 0,"\\" RES 160 ; ; +------------------------+ ; | MENU SCREEN DEFINITION | ; +------------------------+ ; ; THE FOLLOWING WORKSPACE CONTAINS THE SCREEN DEFINITIONS WHICH MUST ; BE DEFINED IN THE MENU.PAR FILE IN STRICT ACCORDANCE WITH THE ; SAMPLE PROVIDED BELOW. THE TOTAL CHARACTER COUNT MUST NEVER ; EXCEED 8K! ; SCREEN:: BYTE "A|DISPLAY DIRECTORY|DIR\\MENU W",0 BYTE "B|DISPLAY DRIVE STATS|DRIVE\\MENU W",0 BYTE "C|DISPLAY DRIVE A DIRECTORY|DIR A:\\MENU W",0 BYTE "D|LOG ONTO MASTER|MASTER",0 BYTE 0XFF RES 8192-(.-SCREEN) ; ; EXPLANATION OF EXAMPLE: ; THE VERTICAL BAR IS A FIELD DELIMITER, THE SINGLE QUOTE IS ; A PROMPT DELIMITER. ; A DEFINITION LINE MUST CONTAIN 4 FIELDS: ; 1. THE RESPONSE CHARACTER WHICH MUST BE ONE SINGLE CHARACTER ; AND MAY BE ANY CHARACTER OTHER THAN 0X00,"'",OR "|" ; 2. THE SELECTION TITLE, WHICH MAY BE A STRING OF UP TO 40 ; CHARACTERS ; 3. THE COMMAND ; (THE COMMAND MAY BE FOLLOWED IMMEDIATELY BY A STRING ENCLOSED ; IN SINGLE QUOTES. IN SUCH A CASE, THE STRING WILL BE DISPLAYED ; BEFORE COMMAND EXECUTION AND A RESPONSE WILL BE SOLICITED FROM ; THE USER WHICH WILL BE PASSED ALONG WITH THE COMMAND. ; THE RESPONSE WILL ONLY BE PARSED FOR A BACKSLASH CHARACTER, ; WHICH IN THIS CONTEXT IS ILLEGAL AND WILL BE IGNORED. ; 4. THE ENDMARK, WHICH IS A NUL (0X00) AND DELIMITS DEFINITION ; LINES. ; ; THE SPECIAL DEFINITION LINE 0XFF DENOTES THE END OF ALL DEFINITIONS ; AND THUS THE END OF THE MENU AND MUST BE PRESENT. ; RES 100 ; ENOUGH STACK SPACE STACK == . ; LOC Code# ; ; +------------------+ ; | START OF PROGRAM | ; +------------------+ ; START: MOV AX,DS ; GET DATA SEGMENT MOV SS,AX ; SET UP STACK SEGMENT RESTRT: MOV SP,&STACK ; AND OFFSET CALL INIPGM ; INITIALIZE THE PROGRAM CMP 0X5D,=BYTE 'W' ; WAIT? JNZ __NWT ; NO MOV CX,=23*256+45 ; BOTTOM LINE, END OF LINE CALL GOTOXY CALL INREV ; REVERSE ON MOV DX,&PRTC ; SEND MESSAGE CALL PRINTM CALL GETCH CALL OUTREV ; REVERSE OFF __NWT: CALL CLS ; CLEAR THE SCREEN MOV DX,&CRLF ; SPACE DOWN A LINE CALL PRINTM MOV BX,&BANNER ; POINT TO BANNER CALL CENTER ; PRINT CENTERED CMP NMBLNS,=20 ; TESTING: OVER 20? JNA __LO MOV CX,=16*256+30 CALL GOTOXY MOV DX,&TOOMNL CALL PRINTM JMP EXIT ; __LO: CALL DSPMNU ; DISPLAY MENU SELECTIONS MOV CX,=4*256+20 ; CURSOR POSITION ; ; THE FOLLOWING LOOP IS USED TO SELECT AN ITEM ; CX PRESERVED THROUGHOUT TO HOLD SCREEN ADDRESS ; SELECT: CALL GOTOXY ; PLACE CURSOR ON SELECTION CALL GETCH ; GET A CHARACTER CMP AL,KEYUP ; KEY UP? JZ __KUP ; YES CMP AL,KEYDN ; KEY DOWN? JZ __KDN ; YES CMP AL,=0X0D ; RETURN? JNZ __KER ; NO, ERROR JMP EXECUT ; ELSE EXECUTE COMMAND ; __KER: CMP AL,KEYXIT ; EXIT KEY? JNZ __NXK ; NO CMP NPRIVX,=0 ; CHECK NONPR FLAG JNZ __EX1 ; EXIT IF SET CMP PRIV,=0 ; PRIV FLAG SET? JNZ __EX1 ; YES __NXK: MOV AL,=0X07 ; BELL CALL PUTCH JMPS SELECT ; __EX1: JMP EXIT ; SPRINGBOARD ; ; KEY UP ; __KUP: DEC CH ; DECREMENT LINE COUNT CMP CH,=3 ; PAST TOP? JNZ SELECT ; NO, LOOP ON MOV CH,BYTE NMBLNS ; ELSE LOAD MAXLINE ADD CH,=3 ; ADD OFFSET JMPS SELECT ; AND LOOP ; ; KEY DOWN ; __KDN: INC CH ; INCREMENT LINE COUNT MOV AX,NMBLNS ; GET LINE COUNT ADD AL,=4 ; ADD OFFSET CMP AL,CH ; BELOW BOTTOM? JNZ SELECT ; NO, CONTINUE MOV CH,=4 ; ELSE LOAD TOP JMPS SELECT ; AND LOOP ; ; COME HERE TO EXECUTE A PROGRAM ; EXECUT: SUB CH,=3 ; NORMALIZE COMMAND POINTER MOV SI,&SCREEN ; POINT TO SCREEN STRING __EXF: DEC CH ; DECREMENT COUNTER JZ __FND ; EXIT LOOP IF FOUND __F0: INC SI CMP [SI],=BYTE 0 JZ __EXF JMPS __F0 ; __FND: INC SI ; STEP PAST EOL INC SI ; STEP PAST COMMAND BYTE __FVB: INC SI CMP [SI],=BYTE '|' ; STEP TO SECOND DELIMITER JNZ __FVB ; LOOP TILL FOUND INC SI ; POINT TO COMMAND STRING MOV DI,&CMDLN+2 ; POINT TO COMMAND LINE MOV AL,=1 ; CONSTRUCTION AREA __ML: MOVS BYTE ; MOVE A BYTE INC AL CMP [SI],=BYTE 0 ; CHECK FOR END JNZ __ML ; LOOP IF NOT MOV CMDLN,AL MOV CL,=18 ; ELSE SEND COMMAND LINE MOV DX,&CMDLN INT TFUNC ; DO IT MOV CL,=17 ; ENABLE AUTOLOAD MOV DL,=0XFF INT TFUNC CALL CLS ; CLEAR THE SCREEN JMP EXITX ; EXIT AND EXECUTE ; EXIT: MOV CX,=22*256+0 ; PLACE CURSOR ON BOTTON OF SCREEN CALL GOTOXY MOV CL,=17 ; DISABLE AUTOLOAD MOV DL,=0 INT TFUNC EXITX: MOV CL,=0 INT CFUNC ; ; +-------------+ ; | SUBROUTINES | ; +-------------+ ; ; DISPLAY MENU SCREEN ; ------------------- ; DSPMNU: MOV SI,&SCREEN ; POINT TO SELECTIONS MOV CX,=4*256+20 ; CURSOR POSITION __DSLP: CALL GOTOXY MOV AL,[SI] CMP AL,=0XFF ; END OF MENU? JNZ __X RET ; YES, RETURN ; __X: CALL PUTCH ; DISPLAY RESPONSE CHARACTER INC SI INC SI ; POINT TO DESCRIPTION MOV DX,&SEP ; DISPLAY SEPARATOR CALL PRINTM __DSDL: MOV AL,[SI] CMP AL,='|' ; DELIMITER? JZ __DSDX ; YES, EXIT CALL PUTCH INC SI JMPS __DSDL ; __DSDX: INC SI CMP [SI],=BYTE 0 JNZ __DSDX INC SI INC CH ; NEXT LINE JMPS __DSLP ; ; CENTER PRINT STRING AT BX ; ------------------------- ; CENTER: PUSH BX ; SAVE STRING POINTER XOR CX,CX ; SET COUNTER TO 0 __CCL: CMP [BX],=BYTE '$' ; END MARK? JZ __CCE ; YES INC BX INC CL JMPS __CCL ; __CCE: MOV AL,CCOLUM ; GET NUMBER OF COLUMNS SUB AL,CL ; SUBTRACT NUMBER OF CHARACTERS SHR AL,=1 ; DIVIDE BY 2 MOV CL,AL ; PUT INTO COUNTER REGISTER MOV AL,=' ' ; SPACE __CCS: CALL PUTCH ; PRINT A SPACE LOOP __CCS ; UNTIL DONE POP DX ; GET STRING POINTER JMP PRINTM ; NOW PRINT IT ; ; POSITION CURSOR ; --------------- ; GOTOXY: PUSH SI MOV SI,&CURAD1 ; SEND LEAD-IN CALL TERCMD CMP CURAD2,=0 ; COL/ROW? JNZ __NCR ; NO, ROW/COL XCHG CH,CL ; ELSE SWAP __NCR: MOV AL,CH ; GET ADDR ADD AL,CURAD4 ; ADD OFFSET CALL PUTCH ; OUTPUT IT MOV AL,CL ; GET SECOND ADDR ADD AL,CURAD4 ; ADD OFFSET CALL PUTCH ; OUTPUT IT POP SI RET ; ; TURN REVERSE ON ; --------------- ; INREV: MOV SI,&CINREV JMPS TERCMD ; ; TURN REVERSE OFF ; ---------------- ; OUTREV: MOV SI,&COTREV JMPS TERCMD ; ; CLEAR THE SCREEN ; ---------------- ; CLS: MOV SI,&CLRSCR ; POINT TO CLEAR SCREEN CODE ; ; SEND TERMINAL COMMAND ; --------------------- ; TERCMD: PUSH AX ; SAVE ACCUMULATOR PUSH CX ; SAVE COUNTER MOV CL,[SI] ; GET NUMBER OF BYTES XOR CH,CH ; MAKE 16 BITS __TCL: INC SI ; POINT TO NEXT BYTE MOV AL,[SI] ; GET BYTE CALL PUTCH ; OUTPUT CHARACTER LOOP __TCL ; REPEAT UNTIL DONE POP CX ; RESTORE REGISTERS POP AX RET ; ; OUTPUT CHARACTER IN AL ; ---------------------- ; PUTCH: PUSH AX ; SAVE MOST REGISTERS PUSH BX PUSH CX PUSH DX PUSH SI MOV CL,=2 MOV DL,AL INT CFUNC POP SI POP DX POP CX POP BX POP AX RET ; ; GET CHARACTER INTO AL ; GETCH: PUSH BX ; SAVE MOST REGISTERS PUSH CX PUSH DX PUSH SI MOV CL,=3 INT CFUNC POP SI POP DX POP CX POP BX RET ; ; PRINT STRING AT DX ; ------------------ ; PRINTM: PUSH BX PUSH CX PUSH DX PUSH SI MOV CL,=9 INT CFUNC POP SI POP DX POP CX POP BX RET ; ; INITIALIZE PROGRAM ; ------------------ ; INIPGM: MOV BX,CS ; SET UP REGISTERS MOV DX,&ABORT ; FOR ABORT TRAP MOV CL,=8 INT TFUNC MOV CL,=12 ; GET PRIVILEGE STATUS INT TFUNC MOV PRIV,CH ; SAVE IT MOV CL,=17 ; ENABLE AUTOLOAD MOV DL,=0XFF INT TFUNC ; ; NOW DETERMINE TOTAL NUMBER OF MENU SELECTIONS ; (SIMPLY COUNT NULL CHARACTERS IN THE DEFINITION SPACE) ; MOV SI,&SCREEN ; POINT TO SCREEN DEF SPACE XOR AX,AX ; CLEAR COUNTER MOV CX,=8192 ; MAX NUMBER OF BYTES __NCL: CMP [SI],=BYTE 0X00 ; DEF LINE END? JZ __DLE ; YES CMP [SI],=BYTE 0XFF ; SCREEN END? JZ __SCE ; YES __C: INC SI ; INCREMENT POINTER LOOP __NCL ; AND CONTINUE MOV DX,&MINVME ; COMPLAIN CALL PRINTM JMP EXIT ; AND QUIT ; __DLE: INC AX ; BUMP COUNTER JMPS __C ; __SCE: MOV NMBLNS,AX ; STORE NUMBER OF LINES RET ; AND RETURN ; ABORT: RETF END RINTM: PUSH BX PUSH CX PUSH DX PUSH SI MOV CL,=9 INT CFUNC POP SI POP DX P .