; * * * * * * * * * * * * START OF SPECIFICATIONS * * * * * * * * * * * * * * * ; ; MODULE NAME: MSGSERV.SAL ; ; DESCRIPTIVE NAME: Message Services SALUT file ; ; FUNCTION: This module incorporates all the messages services and ; is called upon at build time to INCLUDE the code requested ; by a utility. Code is requested using the macro MSG_SERVICES. ; ; ENTRY POINT: Since this a collection of subroutines, entry point is at ; requested procedure. ; ; INPUT: Since this a collection of subroutines, input is dependent on function ; requested. ; ; EXIT-NORMAL: In all cases, CARRY FLAG = 0 ; ; EXIT-ERROR: In all cases, CARRY FLAG = 1 ; ; INTERNAL REFERENCES: (list of included subroutines) ; ; - SYSLOADMSG ; - SYSDISPMSG ; - SYSGETMSG ; ; ; EXTERNAL REFERENCES: None ; ; NOTES: At build time, some modules must be included. These are only included ; once using assembler switches. Other logic is included at the request ; of the utility. ; ; COMR and COMT are assembler switches to conditionally assemble code ; for RESIDENT COMMAND.COM and TRANSIENT COMMAND.COM to reduce resident ; storage and multiple EQUates. ; ; REVISION HISTORY: Created MAY 1987 ; ; Label: DOS - - Message Retriever ; (c) Copyright 1988 Microsoft ; ; ; * * * * * * * * * * * * END OF SPECIFICATIONS * * * * * * * * * * * * * * * * ; Page $SALUT $M (2,5,22,62) ;;AN000;; Set SALUT formatting IF $M_STRUC ;;AN000;; IF we haven't included the structures yet THEN $M_STRUC = FALSE ;;AN000;; Let the assembler know that we have ;;AN000;; and include them PAGE SUBTTL DOS - Message Retriever - MSGSTR.INC Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; STRUCTURE: $M_SUBLIST_STRUC ;; ;; Replacable parameters are described by a sublist structure ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_SUBLIST_STRUC STRUC ;;AN000;; ;; $M_S_SIZE DB 11 ;;AN000;; SUBLIST size (PTR to next SUBLIST) $M_S_RESV DB 0 ;;AN000;; RESERVED $M_S_VALUE DD ? ;;AN000;; Time, Date or PTR to data item $M_S_ID DB ? ;;AN000;; n of %n $M_S_FLAG DB ? ;;AN000;; Data-type flags $M_S_MAXW DB ? ;;AN000;; Maximum field width $M_S_MINW DB ? ;;AN000;; Minimum field width $M_S_PAD DB ? ;;AN000;; Character for Pad field ;; $M_SUBLIST_STRUC ENDS ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; STRUCTURE: $M_CLASS_ID ;; ;; Each class will be defined by this structure. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_CLASS_ID STRUC ;;AN000;; ;; $M_CLS_ID DB -1 ;;AN000;; Class identifer $M_COMMAND_VER DW EXPECTED_VERSION ;;AN003;; COMMAND.COM version check $M_NUM_CLS_MSG DB 0 ;;AN000;; Total number of message in class ;; $M_CLASS_ID ENDS ;; ;;AN000;; $M_CLASS_ID_SZ EQU SIZE $M_CLASS_ID ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; STRUCTURE: $M_ID_STRUC ;; ;; Each message will be defined by this structure. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_ID STRUC ;;AN000;; ;; $M_NUM DW -1 ;;AN000;; Message Number $M_TXT_PTR DW ? ;;AN000;; Pointer to message text ;; $M_ID ENDS ;;AN000;; ;;AN000;; Status Flag Values: $M_ID_SZ EQU SIZE $M_ID ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; STRUCTURE: $M_RES_ADDRS ;; ;; Resident data area definition of variables ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_RES_ADDRS STRUC ;;AN000;; ;; $M_EXT_ERR_ADDRS DD 0 ;;AN000;; Allow pointers to THREE Extended error locations $M_EXT_FILE DD 0 ;;AN001;; $M_EXT_COMMAND DD 0 ;;AN000;; $M_EXT_TERM DD -1 ;;AN000;; $M_PARSE_COMMAND DD 0 ;;AN000;; $M_PARSE_ADDRS DD 0 ;;AN000;; Allow pointers to TWO Parse error locations $M_PARSE_TERM DD -1 ;;AN000;; $M_CRIT_ADDRS DD 0 ;;AN000;; Allow pointers to TWO Critical error locations $M_CRIT_COMMAND DD 0 ;;AN000;; $M_CRIT_TERM DD -1 ;;AN000;; $M_DISK_PROC_ADDR DD -1 ;;AN004;; Address of READ_DISK_PROC $M_CLASS_ADDRS DD $M_NUM_CLS DUP(0) ;;AN000;; Allow pointers to specified classes $M_CLS_TERM DD -1 ;;AN000;; $M_DBCS_VEC DD 0 ;;AN000;; Save DBCS vector $M_HANDLE DW ? ;;AN000;; $M_SIZE DB 0 ;;AN000;; $M_CRLF DB 0DH,0AH ;;AN004;; CR LF message $M_CLASS DB ? ;;AN004;; Saved class $M_RETURN_ADDR DW ? ;;AN000;; $M_MSG_NUM DW $M_NULL ;;AN000;; $M_DIVISOR DW 10 ;;AN000;; Default = 10 (must be a WORD for division) $M_TEMP_BUF DB $M_TEMP_BUF_SZ DUP("$") ;;AN000;; Temporary buffer $M_BUF_TERM DB "$" ;;AN000;; $M_RES_ADDRS ENDS ;;AN000;; ;; $M_RES_ADDRS_SZ EQU SIZE $M_RES_ADDRS ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; STRUCTURE: $M_COUNTRY_INFO ;; ;; Important fields of the Get Country Information call ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_COUNTRY_INFO STRUC ;;AN000;; Expected Country infomation ;; $M_HEADER DB $M_RES_ADDRS_SZ-$M_TEMP_BUF_SZ-1 DUP(?) ;;AN000;; Go past first part of struc $M_DATE_FORMAT DW ? ;;AN000;; <------- Date Format $M_CURR_SEPARA DB 5 DUP(?) ;;AN000;; $M_THOU_SEPARA DB ?,0 ;;AN000;; <------- Thou Separator $M_DECI_SEPARA DB ?,0 ;;AN000;; <------- Decimal Separator $M_DATE_SEPARA DB ?,0 ;;AN000;; <------- Date Separator $M_TIME_SEPARA DB ?,0 ;;AN000;; <------- Time Separator $M_CURR_FORMAT DB ? ;;AN000;; $M_SIG_DIGS_CU DB ? ;;AN000;; $M_TIME_FORMAT DB ? ;;AN000;; <------- Time Format ;; $M_COUNTRY_INFO ENDS ;;AN000;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ELSE ;;AN000;; ELSE if we have already included the STRUCTURES ; $SALUT $M (2,5,13,62) ;;AN000;; Set SALUT formatting for code section IF MSGDATA ;;AN000;; IF this is a request to include the data area MSGDATA = FALSE ;;AN000;; Let the assembler know not to include it again ;;AN000;; and include it PAGE SUBTTL DOS - Message Retriever - MSGRES.TAB Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; DATA NAME: $M_RES_TABLE ;; ;; REFERENCE LABEL: $M_RT ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF COMR ;;AN000;; Since COMMAND.COM includes this twice $M_RT EQU $M_RT2 ;;AN000;; we must redefine the label so no $M_RT2 LABEL BYTE ;;AN000;; assembly errors occur $M_ALTLABEL = TRUE ;;AN000;; Flag that label was changed ELSE ;;AN000;; $M_RT LABEL BYTE ;;AN000;; ENDIF ;;AN000;; $M_RES_ADDRS <> ;;AN000;; Resident addresses ;; include COPYRIGH.INC ;;AN001;; Include Copyright 1988 Microsoft ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of Data table ; IF NOT $M_MSGDATA_ONLY ;;AN000;; IF this was a request for only the data table THEN ;; don't include any more code ;;AN000;; Figure out what other code to include IF DISK_PROC ;;AN003;; Is the request to include the READ_DISK code IF COMR ;;AN003;; (Only Resident COMMAND.COM should ask for it) $M_RT EQU $M_RT2 ;;AN003;; ENDIF DISK_PROC = FALSE ;;AN003;; Yes, THEN include it and reset flag PAGE SUBTTL DOS - Message Retriever - DISK_PROC Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: DISK_PROC ;; ;; FUNCTION: Used in COMMAND.COM if we need to access the Parse or Extended ;; errors from disk\diskette ;; INPUTS: AX has the message number ;; DX has the message class ;; AND ... the COMMAND.COM Variable RESGROUP:COMSPEC is ;; assumed to be set!! ;; ;; OUTPUTS: ES:DI points to message length (BYTE) followed by text ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; PUBLIC READ_DISK_PROC ;; ;; READ_DISK_PROC PROC FAR ;;AN003;; PUSH AX ;;AN003;; Save everything PUSH BX ;;AN003;; PUSH DX ;;AN003;; PUSH SI ;;AN003;; PUSH BP ;;AN003;; PUSH DS ;;AN003;; PUSH DI ;;AN003;; MOV BP,AX ;;AN003;; Save message number MOV AX,DOS_EXTENDED_OPEN ;;AN003;; Set INT 21 function LEA SI,RESGROUP:COMSPEC ;;AN003;; Get addressibilty to COMMAND.COM PUSH CS ;;AN003;; POP DS ;;AN003;; MOV DI,-1 ;;AN003;; No extended attribute list MOV BX,NO_CRIT_OPEN ;;AN003;; Don't generate critical error MOV DX,NOT_EX_FAIL_EX_OPEN ;;AN003;; Open Flag INT 21H ;;AN003;; Open the file POP DI ;;AN003;; Retreive LSEEK pointer ;;AN003;; Error ? $IF NC,LONG ;;AN003;; No, PUSH DI ;;AN003;; Save LSEEK pointer MOV BX,AX ;;AN003;; Set handle in BX MOV AX,DOS_LSEEK_FILE ;;AN003;; LSEEK to the errors XOR CX,CX ;;AN003;; Value has been set by COMMAND.COM MOV DX,DI ;;AN003;; INT 21H ;;AN003;; LSEEK the file POP DX ;;AN003;; Retreive LSEEK pointer ;;AN003;; Error ? $IF NC ;;AN003;; No, INC CX ;;AN003;; Set flag to first pass $DO ;;AN003;; PUSH DX ;;AN003;; Save LSEEK pointer PUSH CX ;;AN003;; Save first pass flag PUSH AX ;;AN003;; Save number of messages (if set yet) XOR SI,SI ;;AN003;; Reset buffer index MOV AH,DOS_READ_BYTE ;;AN003;; Read MOV CX,$M_TEMP_BUF_SZ ;;AN003;; the first part of the header LEA DX,$M_RT.$M_TEMP_BUF ;;AN003;; into the temp buffer INT 21H ;;AN003;; Read it MOV DI,DX ;;AN003;; POP AX ;;AN003;; POP CX ;;AN003;; OR CX,CX ;;AN003;; $IF NZ ;;AN003;; XOR CX,CX ;;AN003;; Set flag to second pass XOR AH,AH ;;AN003;; Get number of messages in class MOV AL,DS:[DI].$M_NUM_CLS_MSG ;;AN003;; MOV SI,$M_CLASS_ID_SZ ;;AN003;; Initialize index CMP DS:[DI].$M_COMMAND_VER,EXPECTED_VERSION ;;AN003;; Is this the right version of COMMAND.COM? $ENDIF ;;AN003;; POP DX ;;AN003;; $IF Z ;;AN003;; Yes, $SEARCH ;;AN003;; CMP BP,WORD PTR $M_RT.$M_TEMP_BUF[SI] ;;AN003;; Is this the message I'm looking for? $EXITIF Z ;;AN003;; Yes, (ZF=1) CLC ;;AN003;; Reset carry, exit search $ORELSE ;;AN003;; No, (ZF=0) ADD SI,$M_ID_SZ ;;AN003;; Increment index ADD DX,$M_ID_SZ ;;AN003;; Add offset of first header DEC AX ;;AN003;; Decrement # of messages left $LEAVE Z ;;AN003;; Have we exhausted all messages? CMP SI,$M_TEMP_BUF_SZ-1 ;;AN003;; No, Have we exhausted the buffer? $ENDLOOP A ;;AN003;; No, Check next message (ZF=1) STC ;;AN003;; Yes, (ZF=0) set error (ZF=0) $ENDSRCH ;;AN003;; $ELSE ;;AN003;; No, XOR CX,CX ;;AN003;; Set Zero flag to exit READ Loop STC ;;AN003;; Set Carry $ENDIF ;;AN003;; $ENDDO Z ;;AN003;; Get next buffer full if needed ;;AN003;; Error ? $IF NC ;;AN003;; No, MOV AX,DOS_LSEEK_FILE ;;AN003;; Prepare to LSEEK to the specific message XOR CX,CX ;;AN003;; Value has been set by COMMAND.COM ADD DX,$M_CLASS_ID_SZ ;;AN003;; Add offset of first header ADD DX,WORD PTR $M_RT.$M_TEMP_BUF[SI]+2 ;;AN003;; Add offset from msg structure INT 21H ;;AN003;; LSEEK the file MOV AH,DOS_READ_BYTE ;;AN003;; Read MOV CX,$M_TEMP_BUF_SZ ;;AN003;; the message LEA DX,$M_RT.$M_TEMP_BUF ;;AN003;; into the temp buffer INT 21H ;;AN003;; Read it MOV DI,DX ;;AN003;; into the temp buffer PUSH DS ;;AN003;; into the temp buffer POP ES ;;AN003;; into the temp buffer $ENDIF ;;AN003;; $ENDIF ;;AN003;; PUSHF ;;AN003;; Close file handle MOV AH,DOS_CLOSE_FILE ;;AN003;; Close file handle INT 21H ;;AN003;; $M_POPF ;;AN003;; $ENDIF ;;AN003;; Yes there was an error, POP DS ;;AN003;; POP BP ;;AN003;; POP SI ;;AN003;; POP DX ;;AN003;; POP BX ;;AN003;; POP AX ;;AN003;; ;;AN003;; abort everything RET ;;AN003;; READ_DISK_PROC ENDP ;;AN003;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN003;; END of include for DISK_PROC ; IF SETSTDIO ;;AN000;; Is the request to include the code for SETSTDIO SETSTDIO = FALSE ;;AN000;; Yes, THEN include it and reset flag PAGE SUBTTL DOS - Message Retriever - SETSTDIO Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: SETSTDIO ;; ;; FUNCTION: ;; INPUTS: ;; ;; OUPUTS: ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF FARmsg ;AN001; SETSTDINON PROC FAR ;AN001; ELSE ;AN001; SETSTDINON PROC NEAR ;AN001; ENDIF ;AN001; PUSH AX ;AN002; Save changed regs PUSH BX ;AN002; PUSH DX ;AN002; MOV AX,DOS_IOCTL_GET_INFO ;AN001; Get info using IOCTL MOV BX,STDIN ;AN001; XOR DX,DX ;AN001; INT 21H ;AN001; OR DH,$M_CRIT_ERR_MASK ;AN001; Turn on bit MOV AX,DOS_IOCTL_SET_INFO ;AN001; Set info using IOCTL INT 21H ;AN001; POP DX ;AN002; Restore Regs POP BX ;AN002; POP AX ;AN002; RET ;AN001; ;AN001; SETSTDINON ENDP ;AN001; IF FARmsg ;AN001; SETSTDINOFF PROC FAR ;AN001; ELSE ;AN001; SETSTDINOFF PROC NEAR ;AN001; ENDIF ;AN001; PUSH AX ;AN002; Save changed regs PUSH BX ;AN002; PUSH DX ;AN002; MOV AX,DOS_IOCTL_GET_INFO ;AN001; Get info using IOCTL MOV BX,STDIN ;AN001; XOR DX,DX ;AN001; INT 21H ;AN001; AND DH,NOT $M_CRIT_ERR_MASK ;AN001; Turn off bit MOV AX,DOS_IOCTL_SET_INFO ;AN001; Set info using IOCTL INT 21H ;AN001; POP DX ;AN002; Restore Regs POP BX ;AN002; POP AX ;AN002; RET ;AN001; SETSTDINOFF ENDP ;AN001; IF FARmsg ;AN001; SETSTDOUTON PROC FAR ;AN001; ELSE ;AN001; SETSTDOUTON PROC NEAR ;AN001; ENDIF ;AN001; PUSH AX ;AN002; Save changed regs PUSH BX ;AN002; PUSH DX ;AN002; MOV AX,DOS_IOCTL_GET_INFO ;AN001; Get info using IOCTL MOV BX,STDOUT ;AN001; XOR DX,DX ;AN001; INT 21H ;AN001; OR DH,$M_CRIT_ERR_MASK ;AN001; Turn on bit MOV AX,DOS_IOCTL_SET_INFO ;AN001; Set info using IOCTL INT 21H ;AN001; POP DX ;AN002; Restore Regs POP BX ;AN002; POP AX ;AN002; RET ;AN001; SETSTDOUTON ENDP ;AN001; IF FARmsg ;AN001; SETSTDOUTOFF PROC FAR ;AN001; ELSE ;AN001; SETSTDOUTOFF PROC NEAR ENDIF ;AN001; PUSH AX ;AN002; Save changed regs PUSH BX ;AN002; PUSH DX ;AN002; MOV AX,DOS_IOCTL_GET_INFO ;AN001; Get info using IOCTL MOV BX,STDOUT ;AN001; XOR DX,DX ;AN001; INT 21H ;AN001; AND DH,NOT $M_CRIT_ERR_MASK ;AN001; Turn off bit MOV AX,DOS_IOCTL_SET_INFO ;AN001; Set info using IOCTL INT 21H ;AN001; POP DX ;AN002; Restore Regs POP BX ;AN002; POP AX ;AN002; RET ;AN001; SETSTDOUTOFF ENDP ;AN001; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include for SETSTDIO ; IF LOADmsg ;;AN000;; Is the request to include the code for SYSLOADMSG ? IF COMR ;;AN000;; $M_RT EQU $M_RT2 ;;AN000;; ENDIF LOADmsg = FALSE ;;AN000;; Yes, THEN include it and reset flag PAGE SUBTTL DOS - Message Retriever - LOADMSG.ASM Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: SYSLOADMSG ;; ;; FUNCTION: ;; INPUTS: ;; ;; OUPUTS: ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF FARmsg ;;AN000;; SYSLOADMSG PROC FAR ;;AN000;; ELSE ;;AN000;; SYSLOADMSG PROC NEAR ;;AN000;; ENDIF ;;AN000;; PUSH AX ;;AN000; PUSH BX ;;AN000; PUSH DX ;;AN000; PUSH ES ;;AN000; PUSH DI ;;AN000; XOR CX,CX ;;AN000; Reset to zero MOV ES,CX ;;AN000; XOR DI,DI ;;AN000; MOV AX,DOS_GET_EXT_PARSE_ADD ;;AN000;; 2FH Interface MOV DL,DOS_GET_EXTENDED ;;AN000;; Where are the Extended errors in COMMAND.COM INT 2FH ;;AN000;; Private interface MOV WORD PTR $M_RT.$M_EXT_COMMAND+2,ES ;;AN000;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_EXT_COMMAND,DI ;;AN000;; ;; MOV AX,DOS_GET_EXT_PARSE_ADD ;;AN000;; 2FH Interface MOV DL,DOS_GET_PARSE ;;AN000;; Where are the Parse errors in COMMAND.COM INT 2FH ;;AN000;; Private interface MOV WORD PTR $M_RT.$M_PARSE_COMMAND+2,ES ;;AN000;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_PARSE_COMMAND,DI ;;AN000;; ;; MOV AX,DOS_GET_EXT_PARSE_ADD ;;AN000;; 2FH Interface MOV DL,DOS_GET_CRITICAL ;;AN000;; Where are the Critical errors in COMMAND.COM INT 2FH ;;AN000;; Private interface MOV WORD PTR $M_RT.$M_CRIT_COMMAND+2,ES ;;AN000;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_CRIT_COMMAND,DI ;;AN000;; MOV AX,DOS_GET_EXT_PARSE_ADD ;;AN001;; 2FH Interface MOV DL,DOS_GET_FILE ;;AN001;; Where are the FILE dependant in IFSFUNC.EXE INT 2FH ;;AN001;; Private interface MOV WORD PTR $M_RT.$M_EXT_FILE+2,ES ;;AN001;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_EXT_FILE,DI ;;AN001;; IF COMR ;; ** Special case for RESIDENT COMMAND.COM IF2 IFNDEF READ_DISK_INFO ;;AN003;; Extrn READ_DISK_PROC:Far ;;AN003;; ENDIF ;;AN003;; ENDIF ;;AN003;; ELSE ;; IF FARmsg ;;AN000;; CALL FAR PTR $M_MSGSERV_1 ;;AN000;; Get addressibilty to MSGSERV CLASS 1 (EXTENDED Errors) ELSE ;;AN000;; CALL $M_MSGSERV_1 ;;AN000;; Get addressibilty to MSGSERV CLASS 1 (EXTENDED Errors) ENDIF ;;AN000;; MOV WORD PTR $M_RT.$M_EXT_ERR_ADDRS+2,ES ;;AN000;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_EXT_ERR_ADDRS,DI ;;AN000;; MOV WORD PTR $M_RT.$M_CRIT_ADDRS+2,ES ;;AN000;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_CRIT_ADDRS,DI ;;AN000;; ;; IF FARmsg ;;AN000;; CALL FAR PTR $M_MSGSERV_2 ;;AN000;; Get addressibilty to MSGSERV CLASS 2 (PARSE Errors) ELSE ;;AN000;; CALL $M_MSGSERV_2 ;;AN000;; Get addressibilty to MSGSERV CLASS 2 (PARSE Errors) ENDIF ;;AN000;; MOV WORD PTR $M_RT.$M_PARSE_ADDRS+2,ES ;;AN000;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_PARSE_ADDRS,DI ;;AN000;; ENDIF ;; ;; MOV AX,DOS_GET_EXT_PARSE_ADD ;;AN001;; 2FH Interface MOV DL,DOS_GET_ADDR ;;AN001;; Where is the READ_DISK_PROC in COMMAND.COM INT 2FH ;;AN001;; Private interface MOV WORD PTR $M_RT.$M_DISK_PROC_ADDR+2,ES ;;AN001;; Move into first avaliable table location MOV WORD PTR $M_RT.$M_DISK_PROC_ADDR,DI ;;AN001;; $M_BUILD_PTRS %$M_NUM_CLS ;;AN000;; Build all utility classes ;;AN000;; CALL $M_GET_DBCS_VEC ;;AN000;; Save the DBCS vector IF NOT NOCHECKSTDIN ;;AN000;; IF EOF check is not to be suppressed CALL $M_CHECKSTDIN ;;AN000;; Set EOF CHECK ENDIF ;;AN000;; ;;AN000;; IF NOT NOCHECKSTDOUT ;;AN000;; IF Disk Full check is not to be suppressed CALL $M_CHECKSTDOUT ;;AN000;; Set Disk Full CHECK ENDIF ;;AN000;; ;;AN000;; IF NOVERCHECKmsg ;;AN000;; IF version check is to be supressed CLC ;;AN000;; Make sure carry is clear ELSE ;;AN000;; ELSE PUSH CX ;;AN000;; CALL $M_VERSION_CHECK ;;AN000;; Check Version ENDIF ;;AN000;; ;; Error ? $IF NC ;;AN000;; No. IF NOT NOVERCHECKmsg ;;AN000;; IF version check was not supressed POP CX ;;AN000;; Reset stack ENDIF ;;AN000;; POP DI ;;AN000;; Restore REGS POP ES ;;AN000;; POP DX ;;AN000;; POP BX ;;AN000;; POP AX ;;AN000;; $ELSE ;;AN000;; Yes, IF NOVERCHECKmsg ;;AN000;; IF version check is to be supressed ADD SP,10 ;;AN000;; STC ;;AN000;; Reset carry flag ELSE ;;AN000;; IF version check is to be supressed ADD SP,12 ;;AN000;; STC ;;AN000;; Reset carry flag ENDIF ;;AN000;; IF version check is to be supressed $ENDIF ;;AN000;; RET ;;AN000;; ;; SYSLOADMSG ENDP ;;AN000;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PAGE SUBTTL DOS - Message Retriever - $M_VERSION_CHECK Proc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proc Name: $M_GET_DBCS_VEC ;; ;; Function: Get the DBCS vector and save it for later use ;; ;; Inputs: None ;; ;; Outputs: None ;; ;; Regs Changed: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_GET_DBCS_VEC PROC NEAR ;;AN000;; ;; PUSH AX ;;AN000;; Save character to check PUSH SI ;;AN000;; PUSH DS ;;AN000;; MOV AX,DOS_GET_DBCS_INFO ;;AN000;; DOS function to get DBSC environment INT 21H ;;AN000;; Get environment pointer PUSH DS ;;AN000;; Get environment pointer POP ES ;;AN000;; Get environment pointer POP DS ;;AN000;; Get environment pointer $IF NC ;;AN000;; MOV WORD PTR $M_RT.$M_DBCS_VEC,SI ;;AN000;; Save DBCS Vector MOV WORD PTR $M_RT.$M_DBCS_VEC+2,ES ;;AN000;; $ENDIF ;;AN000;; POP SI ;;AN000;; POP AX ;;AN000;; Retrieve character to check RET ;;AN000;; Return ;; $M_GET_DBCS_VEC ENDP ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IF NOCHECKSTDIN ;AN001; Are we suppose to include the code for Checking EOF ? ELSE ;AN001; Yes, THEN include it PAGE SUBTTL DOS - Message Retriever - $M_CHECKSTDIN Proc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proc Name: $M_CHECKSTDIN ;; ;; Function: ;; ;; Inputs: None ;; ;; Outputs: ;; ;; Regs Changed: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_CHECKSTDIN PROC NEAR ;AN001; MOV AX,DOS_IOCTL_GET_INFO ;AN001; Get info using IOCTL MOV BX,STDIN ;AN001; XOR DX,DX ;AN001; INT 21H ;AN001; OR DH,$M_CRIT_ERR_MASK ;AN001; Turn on bit MOV AX,DOS_IOCTL_SET_INFO ;AN001; Set info using IOCTL INT 21H ;AN001; RET ;AN001; $M_CHECKSTDIN ENDP ;AN001; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;AN001; END of include for EOF Check IF NOCHECKSTDOUT ;AN001; Are we suppose to include the code for Checking Disk Full? ELSE ;AN001; Yes, THEN include it PAGE SUBTTL DOS - Message Retriever - $M_CHECKSTDOUT Proc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proc Name: $M_CHECKSTDOUT ;; ;; Function: ;; ;; Inputs: None ;; ;; Outputs: ;; ;; Regs Changed: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_CHECKSTDOUT PROC NEAR ;AN001; MOV AX,DOS_IOCTL_GET_INFO ;AN001; Get info using IOCTL MOV BX,STDOUT ;AN001; XOR DX,DX ;AN001; INT 21H ;AN001; OR DH,$M_CRIT_ERR_MASK ;AN001; Turn on bit MOV AX,DOS_IOCTL_SET_INFO ;AN001; Set info using IOCTL INT 21H ;AN001; RET ;AN001; $M_CHECKSTDOUT ENDP ;AN001; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;AN001; END of include for Disk Full Check IF NOVERCHECKmsg ;;AN000;; Are we suppose to include the code for DOS version check? ELSE ;;AN000;; Yes, THEN include it PAGE SUBTTL DOS - Message Retriever - $M_VERSION_CHECK Proc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proc Name: $M_VERSION_CHECK ;; ;; Function: Determine if DOS version is within allowable limits ;; ;; Inputs: None ;; ;; Outputs: CARRY_FLAG = 1 if Incorrect DOS version ;; Registers set for SYSDISPMSG ;; CARRY_FLAG = 0 if Correct DOS version ;; ;; Regs Changed: AX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_VERSION_CHECK PROC NEAR ;;AN000;; ;; MOV AH,DOS_GET_VERSION ;;AN000;; Check that version matches VERSIONA.INC INT 21H ;;AN000;; ;; CMP AX,EXPECTED_VERSION ;;AN000;; IF DOS_MAJOR is correct $IF E ;;AN000;; CLC ;;AN000;; Clear the carry flag $ELSE ;;AN000;; ELSE IF NOT COMR ;; ** Special case for RESIDENT COMMAND.COM CMP AX,LOWEST_4CH_VERSION ;;AN000;; Does this version support AH = 4CH $IF B ;;AN000;; No, MOV BX,NO_HANDLE ;;AN000;; No handle (version doesn't support) $ELSE ;;AN000;; Yes, MOV BX,STDERR ;;AN000;; Standard Error $ENDIF ;;AN000;; ELSE MOV BX,NO_HANDLE ;;AN000;; No handle ENDIF MOV AX,1 ;;AN000;; Set message # 1 MOV CX,NO_REPLACE ;;AN000;; No replacable parms MOV DL,NO_INPUT ;;AN000;; No input MOV DH,UTILITY_MSG_CLASS ;;AN000;; Utility class message STC ;;AN000;; Set Carry Flag $ENDIF ;;AN000;; ;; RET ;;AN000;; Return ;; $M_VERSION_CHECK ENDP ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include for DOS version check ENDIF ;;AN000;; END of include for SYSLOADMSG ; IF GETmsg ;;AN000;; Is the request to include the code for SYSGETMSG ? IF COMR ;;AN000;; $M_RT EQU $M_RT2 ;;AN000;; ENDIF ;;AN000;; GETmsg = FALSE ;;AN000;; Yes, THEN include it and reset flag PAGE SUBTTL DOS - Message Retriever - GETMSG.ASM Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proc Name: SYSGETMSG ;; ;; Function: The GET service returns the segment, offset and size of the ;; message text to the caller based on a message number. ;; The GET function will not display the message thus assumes ;; caller will handle replaceable parameters. ;; ;; Inputs: ;; ;; Outputs: ;; ;; Psuedocode: ;; Call $M_GET_MSG_ADDRESS ;; IF MSG_NUM exists THEN ;; Set DS:SI = MSG_TXT_PTR + 1 ;; CARRY_FLAG = 0 ;; ELSE ;; CARRY_FLAG = 1 ;; ENDIF ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF FARmsg ;;AN000;; SYSGETMSG PROC FAR ;;AN000;; ELSE ;;AN000;; SYSGETMSG PROC NEAR ;;AN000;; ENDIF ;;AN000;; ;; ;; Save registers needed later PUSH AX ;;AN000;; Save changed regs PUSH ES ;;AN000;; PUSH DI ;;AN000;; PUSH BP ;;AN000;; ;; IF FARmsg ;;AN000;; CALL FAR PTR $M_GET_MSG_ADDRESS ;;AN000;; Scan thru classes to find message ELSE ;;AN000;; CALL $M_GET_MSG_ADDRESS ;;AN000;; Scan thru classes to find message ENDIF ;;AN000;; Return message in ES:DI $IF NC ;;AN000;; Message found? CMP DH,UTILITY_MSG_CLASS CLC ;;AN000;; $IF NE PUSH ES ;;AN000;; POP DS ;;AN000;; Return message in DS:SI $ELSE IF FARmsg ;;AN000;; Yes, PUSH ES ;;AN000;; POP DS ;;AN000;; Return message in DS:SI ELSE ;;AN000;; PUSH CS ;;AN000;; Return message in DS:SI POP DS ;;AN000;; ENDIF ;;AN000;; $ENDIF ;;AN000;; MOV SI,DI ;;AN000;; Return message in DS:SI $ENDIF ;;AN000;; ;; POP BP ;;AN000;; Restore changed regs POP DI ;;AN000;; POP ES ;;AN000;; POP AX ;;AN000;; ;; RET ;;AN000;; Return ;; SYSGETMSG ENDP ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IF $M_SUBS ;;AN000;; Include the common subroutines if they haven't yet $M_SUBS = FALSE ;;AN000;; No, then include and reset the flag ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_GET_MSG_ADDRESS ;; ;; FUNCTION: To scan thru classes to return pointer to the message header ;; INPUTS: Access to $M_RES_ADDRESSES ;; OUPUTS: IF CX = 0 THEN Message was not found ;; IF CX > 1 THEN ES:DI points to the specified message ;; REGS CHANGED: ES,DI,CX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF FARmsg ;;AN000;; $M_GET_MSG_ADDRESS PROC FAR ;;AN000;; ELSE ;;AN000;; $M_GET_MSG_ADDRESS PROC NEAR ;;AN000;; ENDIF ;;AN000;; ;; PUSH SI ;;AN000;; PUSH BX ;;AN000;; XOR SI,SI ;;AN000;; Use SI as an index XOR CX,CX ;;AN000;; Use CX as an size $DO ;;AN000;; CMP DH,UTILITY_MSG_CLASS ;;AN000;; Were utility messages requested? $IF E ;;AN000;; Yes, IF FARmsg ;;AN000;; LES DI,DWORD PTR $M_RT.$M_CLASS_ADDRS[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; ELSE ;;AN000;; MOV DI,WORD PTR $M_RT.$M_CLASS_ADDRS[SI] ;;AN000;; Get address of class MOV BX,DI ;;AN000; ENDIF ;;AN000;; $ELSE ;;AN000;; No, TEST DH,PARSE_ERR_CLASS ;;AN000;; Were parse errors requested? $IF NE ;;AN000;; Yes, LES DI,DWORD PTR $M_RT.$M_PARSE_COMMAND[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; $ELSE ;;AN000;; No, extended errors were specified CMP AX,$M_CRIT_LO ;;AN000;; Is this a critical error? $IF AE,AND ;;AN000;; CMP AX,$M_CRIT_HI ;;AN000;; $IF BE ;;AN000;; Yes, LES DI,DWORD PTR $M_RT.$M_CRIT_ADDRS[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; $ELSE ;;AN000;; LES DI,DWORD PTR $M_RT.$M_EXT_ERR_ADDRS[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; $ENDIF ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; CMP BX,$M_TERMINATING_FLAG ;;AN000;; Are we finished all classes? $IF E ;;AN000;; Yes, CMP DH,UTILITY_MSG_CLASS ;;AN000;; Was it a UTILITY class? $IF E ;;AN000;; Yes, STC ;;AN000;; Set the carry flag $ELSE ;;AN000;; No, MOV $M_RT.$M_MSG_NUM,AX ;;AN000;; Save message number MOV AX,$M_SPECIAL_MSG_NUM ;;AN000;; Set special message number MOV BP,$M_ONE_REPLACE ;;AN000;; Set one replace in message XOR SI,SI ;;AN000;; Reset the SI index to start again CLC ;;AN000;; $ENDIF ;;AN000;; No, $ELSE ;;AN000;; CMP BX,$M_CLASS_NOT_EXIST ;;AN000;; Does this class exist? $IF NE ;;AN001;; Yes, CALL $M_FIND_SPECIFIED_MSG ;;AN000;; Try to find the message $ENDIF ;;AN000;; ADD SI,$M_ADDR_SZ_FAR ;;AN000;; Get next class CLC ;;AN000;; $ENDIF ;;AN000;; $LEAVE C ;;AN000;; OR CX,CX ;;AN000;; Was the message found? $ENDDO NZ,LONG ;;AN000;; PUSHF ;;AN006;; Save the flag state CMP DH,EXT_ERR_CLASS ;;AN006;; Was an extended error requested? $IF E ;;AN006;; Yes, PUSH DX ;;AN006;; Save all needed registers PUSH BP ;;AN006;; PUSH CX ;;AN006;; PUSH ES ;;AN006;; PUSH DI ;;AN006;; PUSH AX ;;AN006;; MOV AX,IFSFUNC_INSTALL_CHECK ;;AN006;; Check if IFSFUNC is installed INT 2FH ;;AN006;; CMP AL,IFSFUNC_INSTALLED ;;AN006;; Is it installed? POP AX ;;AN006;; Restore msg number $IF E ;;AN006;; Yes, MOV BX,AX ;;AN006;; BX is the extended error number MOV AX,IFS_GET_ERR_TEXT ;;AN006;; AX is the muliplex number INT 2FH ;;AN006;; Call IFSFUNC $ELSE ;;AN006;; No, STC ;;AN006;; Carry conditon $ENDIF ;;AN006;; $IF C ;;AN006;; Was there an update? POP DI ;;AN006;; No, POP ES ;;AN006;; Restore old pointer POP CX ;;AN006;; $ELSE ;;AN006;; Yes ADD SP,6 ;;AN006;; Throw away old pointer CALL $M_SET_LEN_IN_CX ;;AN006;; Get the length of the ASCIIZ string $ENDIF ;;AN006;; POP BP ;;AN006;; Restore other Regs POP DX ;;AN006;; $ENDIF ;;AN006;; $M_POPF ;;AN006;; Restore the flag state POP BX ;;AN000;; POP SI ;;AN000;; RET ;;AN000;; Return ES:DI pointing to the message ;; $M_GET_MSG_ADDRESS ENDP ;; ;; $M_SET_LEN_IN_CX PROC NEAR ;; ;; PUSH DI ;;AN006;; Save position PUSH AX ;;AN006;; MOV CX,-1 ;;AN006;; Set CX for decrements XOR AL,AL ;;AN006;; Prepare compare register REPNE SCASB ;;AN006;; Scan for zero NOT CX ;;AN006;; Change decrement into number DEC CX ;;AN006;; Don't include the zero POP AX ;;AN006;; POP DI ;;AN006;; Restore position RET ;;AN006;; ;; $M_SET_LEN_IN_CX ENDP ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_FIND_SPECIFIED_MSG ;; ;; FUNCTION: To scan thru message headers until message is found ;; INPUTS: ES:DI points to beginning of msg headers ;; CX contains the number of messages in class ;; DH contains the message class ;; OUPUTS: IF CX = 0 THEN Message was not found ;; IF CX > 1 THEN ES:DI points to header of specified message ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_FIND_SPECIFIED_MSG PROC NEAR ;;AN000;; ;; CMP BX,1 ;;AN004;; Do we have an address to CALL? $IF E,AND ;;AN004;; Yes, CMP WORD PTR $M_RT.$M_DISK_PROC_ADDR,-1 ;;AN004;; Do we have an address to CALL? $IF NE ;;AN004;; Yes, CMP AX,$M_SPECIAL_MSG_NUM ;;AN004;; Are we displaying a default Ext Err? $IF E ;;AN004;; . . . and . . . PUSH AX ;;AN004;; Reset the special message number MOV AX,$M_RT.$M_MSG_NUM ;;AN004;; Get the old message number CALL DWORD PTR $M_RT.$M_DISK_PROC_ADDR ;;AN004;; Call the READ_DISK_PROC to get error text POP AX ;;AN004;; Reset the special message number $ELSE ;;AN004;; Get the old message number CALL DWORD PTR $M_RT.$M_DISK_PROC_ADDR ;;AN004;; Call the READ_DISK_PROC to get error text $ENDIF ;;AN004;; Get the old message number $ELSE ;;AN004;; XOR CX,CX ;;AN002;; CX = 0 will allow us to CMP DH,UTILITY_MSG_CLASS ;;AN001;; $IF NE ;;AN001;; MOV CL,BYTE PTR ES:[DI].$M_NUM_CLS_MSG ;;AN001;; Get number of messages in class $ELSE ;;AN001;; IF FARmsg ;;AN001;; CMP BYTE PTR ES:[DI].$M_CLASS_ID,DH ;;AN002;; Check if class still exists at ELSE CMP BYTE PTR CS:[DI].$M_CLASS_ID,DH ;;AN002;; Check if class still exists at ENDIF $IF E ;;AN002;; pointer (hopefully) IF FARmsg ;;AN001;; MOV CL,BYTE PTR ES:[DI].$M_NUM_CLS_MSG ;;AN000;; Get number of messages in class ELSE MOV CL,BYTE PTR CS:[DI].$M_NUM_CLS_MSG ;;AN000;; Get number of messages in class ENDIF $ENDIF ;;AN002;; go on to the next class $ENDIF ;;AN001;; ADD DI,$M_CLASS_ID_SZ ;;AN000;; Point past the class header STC ;;AN004;; Flag that we haven't found anything yet $ENDIF ;;AN004;; $IF C ;;AN004;; Have we found anything yet? CLC ;;AN004;; No, reset carry $SEARCH ;;AN000;; OR CX,CX ;;AN000;; Do we have any to check? $LEAVE Z ;;AN000;; No, return with CX = 0 CMP DH,UTILITY_MSG_CLASS ;;AN001;; $IF NE ;;AN001;; CMP AX,WORD PTR ES:[DI].$M_NUM ;;AN001;; Is this the message requested? $ELSE ;;AN001;; IF FARmsg ;;AN001;; CMP AX,WORD PTR ES:[DI].$M_NUM ;;AN000;; Is this the message requested? ELSE CMP AX,WORD PTR CS:[DI].$M_NUM ;;AN000;; Is this the message requested? ENDIF $ENDIF $EXITIF E ;;AN000;; $ORELSE ;;AN000; DEC CX ;;AN000;; No, well do we have more to check? $LEAVE Z ;;AN000;; No, return with CX = 0 ADD DI,$M_ID_SZ ;;AN000;; Yes, skip past msg header $ENDLOOP ;;AN000;; STC ;;AN000;; $ENDSRCH ;;AN000;; Check next message $IF NC ;;AN000;; Did we find the message? CMP DH,UTILITY_MSG_CLASS ;;AN001;; Yes, is it a utility message? CLC ;;AN001;; $IF E ;;AN001;; IF FARmsg ;;AN001;; ELSE ;;AN000;; PUSH CS ;;AN000;; POP ES ;;AN000;; Return ES:DI pointing to the message ENDIF $ENDIF ;;AN001;; ADD DI,WORD PTR ES:[DI].$M_TXT_PTR ;;AN000;; Prepare ES:DI pointing to the message $ENDIF ;;AN004;; $ENDIF ;;AN004;; ;; Yes, great we can return with CX > 0 $IF NC ;;AN000;; Did we find the message? XOR CH,CH ;;AN000;; MOV CL,BYTE PTR ES:[DI] ;;AN000;; Move size into CX INC DI ;;AN000;; Increment past length $ENDIF ;;AN004;; MOV $M_RT.$M_SIZE,$M_NULL ;;AN004;; Reset variable RET ;;AN000;; Return ;; $M_FIND_SPECIFIED_MSG ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of common subroutines ENDIF ;;AN000;; END of include of SYSGETMSG ; IF DISPLAYmsg ;;AN000;; Is the request to include the code for SYSGETMSG ? IF COMR ;;AN000;; $M_RT EQU $M_RT2 ;;AN000;; ENDIF ;;AN000;; DISPLAYmsg = FALSE ;;AN000;; Yes, THEN include it and reset flag PAGE SUBTTL DOS - Message Retriever - DISPMSG.ASM Module ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proc Name: SYSDISPMSG ;; ;; Function: The DISPLAY service will output a defined message to a handle ;; requested by the caller. It also provides function to display ;; messages when handles are not applicable (ie. DOS function calls ;; 00h to 0Ah) Replaceable parameters are allowed and are ;; defined previous to entry. ;; ;; It is assumes that a PRELOAD function has already determined ;; the addressibilty internally to the message retriever services. ;; Inputs: ;; ;; Outputs: ;; ;; Psuedocode: ;; Save registers needed later ;; Get address of the message requested ;; IF Message number exists THEN ;; IF replacable parameters were specified THEN ;; Display message with replacable parms ;; ELSE ;; Display string without replacable parms ;; ENDIF ;; IF character input was requested THEN ;; Wait for character input ;; ENDIF ;; Clear CARRY FLAG ;; ELSE ;; Set CARRY FLAG ;; ENDIF ;; Return ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF FARmsg ;;AN000;; SYSDISPMSG PROC FAR ;;AN000;; ELSE ;;AN000;; SYSDISPMSG PROC NEAR ;;AN000;; ENDIF ;;AN000;; ;; ;; Save registers and values needed later PUSH AX ;;AN000;; Save changed REGs PUSH BX ;;AN000;; PUSH CX ;;AN000;; PUSH BP ;;AN000;; PUSH DI ;;AN000;; Save pointer to input buffer (offset) PUSH ES ;;AN000;; Save pointer to input buffer (segment) PUSH DX ;;AN000;; Save Input/Class request MOV BP,CX ;;AN000;; Use BP to hold replace count MOV WORD PTR $M_RT.$M_HANDLE,BX ;;AN000;; Save handle MOV BYTE PTR $M_RT.$M_CLASS,DH ;;AN004;; Save class ;; Get address of the message requested IF FARmsg ;;AN000;; CALL FAR PTR $M_GET_MSG_ADDRESS ;;AN000;; Scan thru classes to find message ELSE ;;AN000;; CALL $M_GET_MSG_ADDRESS ;;AN000;; Scan thru classes to find message ENDIF ;;AN000;; OR CX,CX ;;AN000;; Was message found? $IF NZ ;;AN000;; YES, Message address in ES:DI ;; Test if replacable parameters were specified OR BP,BP ;;AN000;; Were replacable parameters requested $IF Z ;;AN000;; ;; Display string without replacable parms CALL $M_DISPLAY_STRING ;;AN000;; No, great . . . Display message $ELSE ;;AN000;; IF $M_REPLACE ;;AN000;; ;; Display message with replacable parms CALL $M_DISPLAY_MESSAGE ;;AN000;; Display the message with substitutions ENDIF ;;AN000;; $ENDIF ;;AN000;; $IF NC POP DX ;;AN000;; Get Input/Class request CALL $M_ADD_CRLF ;;AN004;; Check if we need to add the CR LF chars. POP ES ;;AN000;; Get location of input buffer (if specified) POP DI ;;AN000;; ;; Test if character input was requested IF INPUTmsg ;;AN000;; OR DL,DL ;;AN000;; Was Wait-For-Input requested? $IF NZ ;;AN000;; CALL $M_WAIT_FOR_INPUT ;;AN000;; $ENDIF ;;AN000;; ENDIF ;;AN000;; $ELSE ;;AN000;; ADD SP,6 ;;AN000;; STC ;;AN000;; Reset carry flag $ENDIF ;;AN000;; $ELSE ;;AN000;; No, POP ES ;;AN000;; Get pointer to input buffer (segment) POP DI ;;AN000;; Get base pointer to first sublist (offset) POP DX ;;AN000;; Get base pointer to first sublist (segment) STC ;;AN000;; Set carry flag $ENDIF ;;AN000;; ;; $IF NC ;;AN000;; Was there an error? POP BP ;;AN000;; No, POP CX ;;AN000;; POP BX ;;AN000;; IF INPUTmsg ;;AN000;; ADD SP,2 ;;AN000;; ELSE ;AN000; POP AX ;;AN000;; ENDIF ;;AN000;; $ELSE ;;AN000;; Yes, ADD SP,8 ;;AN000;; Eliminate from stack STC ;;AN000;; $ENDIF ;;AN000;; ;; RET ;;AN000;; Return ;; SYSDISPMSG ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;; ;; PROC NAME: $M_DISPLAY_STRING ;; ;; FUNCTION: Will display or write string ;; INPUTS: ES:DI points to beginning of message ;; CX contains the length of string to write (if applicable) ;; OUTPUTS: None ;; REGS Revised: None ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_DISPLAY_STRING PROC NEAR ;;AN000;; ;; PUSH AX ;;AN000;; PUSH BX ;;AN000;; PUSH DX ;;AN000;; ;; MOV BX,$M_RT.$M_HANDLE ;;AN000;; Retrieve handle ;; IF COMR ;; ** Special case for RESIDENT COMMAND.COM CALL $M_DISPLAY_$_STRING ;;AN000;; No, display $ terminated string ELSE CMP BX,$M_NO_HANDLE ;;AN000;; Was there a handle specified? $IF E ;;AN000;; CALL $M_DISPLAY_$_STRING ;;AN000;; No, display $ terminated string $ELSE ;;AN000;; CALL $M_DISPLAY_H_STRING ;;AN000;; Yes, display string to handle $ENDIF ;;AN000;; ;AN001; $IF C ;;AN000;; Was there an error? MOV AH,DOS_GET_EXT_ERROR ;;AN000;; Yes, MOV BX,DOS_GET_EXT_ERROR_BX ;;AN000;; Get extended error INT 21H ;;AN000;; XOR AH,AH ;;AN000;; Clear AH ADD SP,6 ;;AN000;; Clean up stack STC ;;AN000;; Flag that there was an error $ELSE ;;AN000;; No, CMP BX,$M_NO_HANDLE ;;AN000;; Was there a handle specified? $IF NE ;;AN000;; CMP AX,CX ;AN001; Was it ALL written? $IF NE ;AN001; No, CALL $M_GET_EXT_ERR_39 ;AN001; Set Extended error ADD SP,6 ;AN001; Clean up stack STC ;AN001; Flag that there was an error $ENDIF ;AN001; $ENDIF ;AN001; $ENDIF ;;AN000;; ENDIF $IF NC ;;AN000;; Was there ANY error? POP DX ;;AN000;; Restore regs POP BX ;;AN000;; POP AX ;;AN000;; $ENDIF ;;AN000;; RET ;;AN000;; Return ;; $M_DISPLAY_STRING ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_DISPLAY_$_STRING ;; ;; FUNCTION: Will display a $ terminated string ;; INPUTS: ES:DI points to beginning of message text (not the length) ;; OUPUTS: None ;; REGS USED: AX,DX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_DISPLAY_$_STRING PROC NEAR ;;AN000;; ;; PUSH DS ;;AN000;; PUSH ES ;;AN000;; POP DS ;;AN000;; Set DS to segment of message text IF NOT COMR CMP CX,$M_SINGLE_CHAR ;;AN000;; Is this a single character? $IF E ;;AN000;; Yes, MOV AH,DOS_DISP_CHAR ;;AN000;; DOS Function to display CHARACTER MOV DL,BYTE PTR ES:[DI] ;;AN000;; Get the character INT 21H ;;AN000;; Write character POP DS ;;AN000;; Set DS to segment of message text MOV AL,DL ;;AN000;; Get the character in AL CALL $M_IS_IT_DBCS ;;AN000;; Is this the first byte of a DB character PUSH DS ;;AN000;; PUSH ES ;;AN000;; POP DS ;;AN000;; Set DS to segment of message text $IF C ;;AN000;; Yes, MOV DL,BYTE PTR ES:[DI]+1 ;;AN000;; Get the next character INT 21H ;;AN000;; Write character CLC ;;AN000;; Clear the DBCS indicator $ENDIF ;;AN000;; $ELSE ;;AN000;; No, ENDIF MOV AH,DOS_DISP_CHAR ;;AN000;; DOS Function to display CHARACTER $DO ;;AN002;; No, OR CX,CX ;;AN002;; Are there any left to display? $LEAVE Z ;;AN002;; Yes, MOV DL,BYTE PTR ES:[DI] ;;AN002;; Get the character INT 21H ;;AN002;; Display the character INC DI ;;AN002;; Set pointer to next character DEC CX ;;AN002;; Count this character $ENDDO Z ;;AN002;; No, IF NOT COMR $ENDIF ;;AN000;; ENDIF CLC ;;AN000;; Char functions used don't return carry as error POP DS ;;AN000;; RET ;;AN000;; ;; $M_DISPLAY_$_STRING ENDP ;;AN000;; ;; IF NOT COMR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_DISPLAY_H_STRING ;; ;; FUNCTION: Will display a string to a specified handle ;; INPUTS: ES:DI points to beginning of message ;; CX contains the number of bytes to write ;; BX contains the handle to write to ;; OUPUTS: None ;; REGS USED: AX,DX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_DISPLAY_H_STRING PROC NEAR ;;AN000;; ;; XOR AX,AX ;;AN002;; Set number of bytes written to 0 OR CX,CX ;;AN002;; For performance, don't write if not necessary $IF NZ ;;AN002;; Any chars to write? PUSH DS ;;AN000;; Yes, PUSH ES ;;AN000;; POP DS ;;AN000;; Set DS to segment of message text MOV AH,DOS_WRITE_HANDLE ;;AN000;; DOS function to write to a handle MOV DX,DI ;;AN000;; Pointer to data to write CMP CX,$M_SINGLE_CHAR ;;AN000;; Is this a single character? $IF E ;;AN000;; Yes, INT 21H ;;AN000;; Write character POP DS ;;AN000;; Set DS to segment of message text PUSH AX ;;AN000;; MOV AL,BYTE PTR ES:[DI] ;;AN000;; Get the character CALL $M_IS_IT_DBCS ;;AN000;; Is this the first byte of a DB character POP AX ;;AN000;; Set DS to segment of message text PUSH DS ;;AN000;; PUSH ES ;;AN000;; POP DS ;;AN000;; Set DS to segment of message text $IF C ;;AN000;; Yes, CLC ;;AN000;; Clear the DBCS indicator MOV AH,DOS_WRITE_HANDLE ;;AN000;; DOS function to write to a handle INC DX ;;AN000;; Point to next character INT 21H ;;AN000;; Write character $ENDIF ;;AN000;; $ELSE ;;AN000;; No, INT 21H ;;AN000;; Write String at DS:SI to handle $ENDIF ;;AN000;; POP DS ;;AN000;; $ENDIF ;;AN002;; ;; RET ;;AN000;; ;; $M_DISPLAY_H_STRING ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_GET_EXT_ERR_39 ;; ;; FUNCTION: Will set registers for extended error #39 ;; INPUTS: None ;; OUPUTS: AX,BX,CX set ;; REGS USED: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_GET_EXT_ERR_39 PROC NEAR ;AN001; ;; MOV AX,EXT_ERR_39 ;AN001; Set AX=39 MOV BX,(ERROR_CLASS_39 SHR 8) + ACTION_39 ;AN001; Set BH=1 BL=4 MOV CH,LOCUS_39 ;AN001; Set CH=1 ;AN001; RET ;AN001; ;; $M_GET_EXT_ERR_39 ENDP ;AN001; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;; ;; PROC NAME: $M_ADD_CRLF ;; ;; FUNCTION: Will decide whether to display a CRLF ;; INPUTS: DX contains the Input/Class requested ;; OUTPUTS: None ;; REGS Revised: CX,ES,DI ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_ADD_CRLF PROC NEAR ;;AN004;; ;; CMP DH,UTILITY_MSG_CLASS ;;AN004;; Is it a utility message? $IF NE ;;AN004;; No, TEST DH,$M_NO_CRLF_MASK ;;AN004;; Are we to supress the CR LF? $IF Z ;;AN004;; No, PUSH DS ;;AN004;; POP ES ;;AN004;; Set ES to data segment LEA DI,$M_RT.$M_CRLF ;;AN004;; Point at CRLF message MOV CX,$M_CRLF_SIZE ;;AN004;; Set the message size CALL $M_DISPLAY_STRING ;;AN004;; Display the CRLF $ENDIF ;;AN004;; $ENDIF ;;AN004;; RET ;;AN004;; Return ;; $M_ADD_CRLF ENDP ;;AN004;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_IS_IT_DBCS ;; ;; FUNCTION: Will decide whether character is Single or Double Byte ;; INPUTS: AL contains the byte to be checked ;; OUPUTS: Carry flag = 0 if byte is NOT in DBCS range ;; Carry flag = 1 if byte IS in DBCS range ;; REGS USED: All restored ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_IS_IT_DBCS PROC NEAR ;;AN000;; ;; PUSH ES ;;AN000;; Save Extra segment register PUSH DI ;;AN000;; Save SI register ;; LES DI,$M_RT.$M_DBCS_VEC ;;AN000;; OR DI,DI ;;AN000;; Was the DBCS vector set? $IF NZ ;;AN000;; $DO ;;AN000;; CMP WORD PTR ES:[DI],$M_DBCS_TERM ;;AN000;; Is this the terminating flag? CLC ;;AN000;; $LEAVE E ;;AN000;; ;; No, CMP AL,BYTE PTR ES:[DI] ;;AN000;; Does the character fall in the DBCS range? $IF AE,AND ;;AN000;; CMP AL,BYTE PTR ES:[DI]+1 ;;AN000;; Does the character fall in the DBCS range? $IF BE ;;AN000;; STC ;;AN000;; Yes, $ENDIF ;;AN000;; Set carry flag INC DI ;;AN000;; No, INC DI ;;AN000;; Go to next vector $ENDDO ;;AN000;; $ENDIF ;;AN000;; POP DI ;;AN000;; POP ES ;;AN000;; Restore SI register RET ;;AN000;; Return ;; $M_IS_IT_DBCS ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_CONVERT2ASC ;; ;; FUNCTION: Convert a binary number to a ASCII string ;; INPUTS: DX:AX contains the number to be converted ;; $M_RT_DIVISOR contains the divisor ;; OUPUTS: CX contains the number of characters ;; Top of stack --> Last character ;; . . . ;; Bot of stack --> First character ;; REGS USED: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_CONVERT2ASC PROC NEAR ;;AN000;; ;; POP [$M_RT.$M_RETURN_ADDR] ;;AN000;; Save Return Address XOR BX,BX ;;AN000;; Use BP as a swapping register ;; XCHG BX,AX ;;AN000;; Initialize - Low Word in BP XCHG AX,DX ;;AN000;; - High Word in AX $DO ;;AN000;; DO UNTIL Low Word becomes zero DIV $M_RT.$M_DIVISOR ;;AN000;; Divide High Word by divisor XCHG BX,AX ;;AN000;; Setup to divide Low Word using remainder ;; and save reduced High Word in BP DIV $M_RT.$M_DIVISOR ;;AN000;; Divide Low Word by divisor CMP DX,9 ;;AN000;; Make a digit of the remainder $IF A ;;AN000;; IF 10 to 15, ADD DL,55 ;;AN000;; Make A to F ASCII $ELSE ;;AN000;; IF 0 to 9, ADD DL,'0' ;;AN000;; Make 0 to 9 ASCII $ENDIF ;;AN000;; PUSH DX ;;AN000;; Save the digit on the stack INC CX ;;AN000;; Count that digit OR AX,AX ;;AN000;; Are we done? $LEAVE Z,AND ;;AN000;; OR BX,BX ;;AN000;; AX and BX must be ZERO!! $LEAVE Z ;;AN000;; No, IF NOT COMR CMP CX,$M_FIRST_THOU ;;AN000;; Are we at the first thousands mark $IF E ;;AN000;; Yes, CMP $M_SL.$M_S_PAD,$M_COMMA ;;AN000;; Is the pad character a comma? $IF E ;;AN000;; Yes, PUSH WORD PTR $M_RT.$M_THOU_SEPARA ;;AN000;; Insert a thousand separator INC CX ;;AN000;; $ENDIF ;;AN000;; $ELSE ;;AN000;; No, CMP CX,$M_SECOND_THOU ;;AN000;; Are we at the first thousands mark $IF E ;;AN000;; Yes, CMP $M_SL.$M_S_PAD,$M_COMMA ;;AN000;; Is the pad character a comma? $IF E ;;AN000;; Yes, PUSH WORD PTR $M_RT.$M_THOU_SEPARA ;;AN000;; Insert a thousand separator INC CX ;;AN000;; $ENDIF ;;AN000;; $ELSE ;;AN000;; No, CMP CX,$M_THIRD_THOU ;;AN000;; Are we at the first thousands mark $IF E ;;AN000;; Yes, CMP $M_SL.$M_S_PAD,$M_COMMA ;;AN000;; Is the pad character a comma? $IF E ;;AN000;; Yes, PUSH WORD PTR $M_RT.$M_THOU_SEPARA ;;AN000;; Insert a thousand separator INC CX ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; ENDIF XCHG AX,BX ;;AN000;; Setup to divide the reduced High Word ;;AN000;; and Revised Low Word XOR DX,DX ;;AN000;; Reset remainder $ENDDO ;;AN000;; NEXT ;;AN000;; Yes, XOR DX,DX ;;AN000;; Reset remainder XOR AX,AX ;;AN000;; Reset remainder PUSH [$M_RT.$M_RETURN_ADDR] ;;AN000;; Restore Return Address RET ;;AN000;; Return ;; $M_CONVERT2ASC ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_DISPLAY_MESSAGE ;; ;; FUNCTION: Will display or write entire message (with replacable parameters) ;; INPUTS: ES:DI points to beginning of message ;; DS:SI points to first sublist structure in chain ;; BX contains the handle to write to (if applicable) ;; CX contains the length of string to write (before substitutions) ;; BP contains the count of replacables ;; ;; OUTPUTS: ;; REGS USED: All ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_DISPLAY_MESSAGE PROC NEAR ;;AN000;; ;; $DO ;;AN000;; Note: DS:SI -> message XOR DX,DX ;;AN000;; Set size = 0 OR CX,CX ;;AN000;; Are we finished the message yet? $IF NZ ;;AN000;; No, MOV AH,"%" ;;AN000;; Prepare to scan for % MOV AL,0 ;;AN004;; ;; $DO ;;AN000;; Scan through string until % CMP BYTE PTR ES:[DI],AH ;;AN000;; Is this character NOT a % $LEAVE E,AND ;;AN000;; No, CMP BYTE PTR ES:[DI+1],AH ;;AN000;; Is the next character also a % $LEAVE NE,AND ;;AN000;; No, CMP AL,AH ;;AN000;; Was the character before a % $LEAVE NE ;;AN000;; No, GREAT found it MOV AL,BYTE PTR ES:[DI] ;;AN004;; Yes, (to any of the above) CALL $M_IS_IT_DBCS ;;AN004;; Is this character the first part of a DBCS? $IF C ;;AN004;; Yes, INC DI ;;AN004;; Increment past second part $ENDIF ;;AN004;; INC DI ;;AN000;; Next character in string INC DX ;;AN000;; Size = Size + 1 DEC CX ;;AN000;; Decrement total size $ENDDO Z ;;AN000;; Exit scan if we're at the end of the line $ENDIF ;;AN000;; ;; PUSH SI ;;AN000;; Save beginning of sublists XCHG CX,DX ;;AN000;; Get size of message to display (tot sz in DX) OR BP,BP ;;AN000;; Do we have any replacables to do? $IF NZ ;;AN000;; Yes, DEC BP ;;AN000;; Decrement number of replacables ;; Search through sublists to find applicable one CMP $M_RT.$M_MSG_NUM,$M_NULL ;;AN000;; Is this an Extended/Parse case $IF E ;;AN000;; No, $SEARCH ;;AN000;; MOV AL,$M_SL.$M_S_ID ;;AN000;; Get ID byte ADD AL,30H ;;AN000;; Convert to ASCII CMP AL,BYTE PTR ES:[DI]+1 ;;AN000;; Is this the right sublist? $EXITIF E ;;AN000;; $ORELSE ;;AN000;; No, CMP AL,$M_SPECIAL_CASE ;;AN000;; Does this sublist have ID = 0 $LEAVE E,AND ;;AN000;; Yes, OR DX,DX ;;AN000;; Are we at the end of the message? $LEAVE Z ;;AN000;; No, ADD SI,WORD PTR $M_SL.$M_S_SIZE ;;AN000;; Next SUBLIST $ENDLOOP ;;AN000;; Yes, CMP $M_RT.$M_CLASS,UTILITY_MSG_CLASS ;;AN004;; Is it a utility message? $IF E ;;AN004;; Yes, INC DX ;;AN000;; Remember to display CR,LF INC DX ;;AN000;; at the end of the message DEC CX ;;AN000;; Adjust message length DEC CX ;;AN000;; DEC DI ;;AN000;; Adjust ending address of message DEC DI ;;AN000;; $ELSE ;;AN004;; No, MOV DX,-1 ;;AN004;; Set special case $ENDIF ;;AN004;; $ENDSRCH ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; Prepare and display this part of message PUSH DI ;;AN000;; Save pointer to replace number SUB DI,CX ;;AN000;; Determine beginning of string CALL $M_DISPLAY_STRING ;;AN000;; Display string until % (or end) POP DI ;;AN000;; Get back pointer to replace number POP CX ;;AN000;; Clean up stack in case error $LEAVE C,LONG ;;AN000;; Fail if carry was set PUSH CX ;;AN000;; ;; Save and reset pointer registers MOV CX,DX ;;AN000;; Get the size of the rest of the message CMP $M_SL.$M_S_ID,$M_SPECIAL_CASE-30H ;;AN000;; Is this the %0 case? $IF NE ;;AN000;; No, OR CX,CX ;;AN000;; Are we finished the whole message? $IF NZ ;;AN000;; No, DEC CX ;;AN000;; Decrement total size (%) DEC CX ;;AN000;; Decrement total size (#) INC DI ;;AN000;; Go past % INC DI ;;AN000;; Go past replace number $ELSE ;;AN000;; Yes, (Note this will not leave because INC) POP SI ;;AN000;; Get back pointer to beginning of SUBLISTs $ENDIF ;;AN000;; Yes, Note this will not leave because INC $ELSE ;;AN000;; OR CX,CX ;;AN000;; Are we finished the whole message? $IF Z ;;AN004;; No, POP SI ;;AN000;; Get back pointer to beginning of SUBLISTs $ELSE ;;AN000;; No, CMP CX,-1 ;;AN004;; Are we at the end of the message? $IF Z ;;AN004;; No, XOR CX,CX ;;AN004;; $ENDIF ;;AN000;; OR DI,DI ;;AN004;; Turn ZF off $ENDIF ;;AN000;; $ENDIF ;;AN000;; Note this will not leave because INC $LEAVE Z ;;AN000;; PUSH BP ;;AN000;; Save the replace count PUSH DI ;;AN000;; Save location to complete message PUSH ES ;;AN000;; PUSH CX ;;AN000;; Save size of the rest of the message XOR CX,CX ;;AN000;; Reset CX used for character count ;; Determine what action is required on parameter CMP $M_RT.$M_MSG_NUM,$M_NULL ;;AN000;; Is this an Extended/Parse case $IF E ;;AN000;; IF CHARmsg ;;AN000;; Was Char specified? TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Char_Type AND $M_TYPE_MASK ;;AN000;; $IF Z ;;AN000;; ;; Character type requested ;;AN000;; LES DI,DWORD PTR $M_SL.$M_S_VALUE ;;AN000;; Load pointer to replacing parameter CALL $M_CHAR_REPLACE ;;AN000;; $ELSE ;;AN000;; Get the rest of the message to display ENDIF ;;AN000;; IF NUMmsg ;;AN000;; Was Nnmeric type specified? TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; $IF Z,OR ;;AN000;; TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; $IF Z,OR ;;AN000;; TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Bin_Hex_Type AND $M_TYPE_MASK ;;AN000;; $IF Z ;;AN000;; ;; Numeric type requested LES DI,DWORD PTR $M_SL.$M_S_VALUE ;;AN000;; Load pointer to replacing parameter CALL $M_BIN2ASC_REPLACE ;;AN000;; $ELSE ;;AN000;; Get the rest of the message to display ENDIF ;;AN000;; IF DATEmsg ;;AN000;; Was date specified? TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Date_Type AND $M_TYPE_MASK ;;AN000;; $IF E ;;AN000;; ;; Date type requested CALL $M_DATE_REPLACE ;;AN000;; $ELSE ;;AN000;; Get the rest of the message to display ENDIF ;;AN000;; IF TIMEmsg ;;AN000;; Was time (12 hour format) specified? ;; Time type requested (Default if we have not matched until here) CALL $M_TIME_REPLACE ;;AN000;; ENDIF ;;AN000;; IF DATEmsg ;;AN000;; $ENDIF ;;AN000;; ENDIF ;;AN000;; IF NUMmsg ;;AN000;; $ENDIF ;;AN000;; ENDIF ;;AN000;; IF CHARmsg ;;AN000;; $ENDIF ;;AN000;; ENDIF ;;AN000;; IF $M_REPLACE ;;AN000;; ;; With the replace information of the Stack, display the replaceable field CALL $M_DISPLAY_REPLACE ;;AN000;; Display the replace ENDIF ;;AN000;; ;; None of the above - Extended/Parse replace $ELSE ;;AN000;; IF NOT COMR CALL $M_EXT_PAR_REPLACE ;;AN000;; ENDIF $ENDIF ;;AN000;; ;; We must go back and complete the message after the replacable parameter if there is any left $IF NC ;;AN000;; IF there was an error displaying then EXIT POP CX ;;AN000;; Get size of the rest of the message POP ES ;;AN000;; Get address of the rest of the message POP DI ;;AN000;; POP BP ;;AN000;; Get replacment count POP SI ;;AN000;; ELSE get address of first sublist structure $ELSE ;;AN000;; ADD SP,10 ;;AN000;; Clean up stack if error STC ;;AN000;; $ENDIF ;;AN000;; CMP $M_RT.$M_MSG_NUM,$M_NULL ;;AN000;; Is this an Extended/Parse case $ENDDO NE,OR ;;AN000;; $ENDDO C,LONG ;;AN000;; Go back and display the rest of the message ;; IF there was an error displaying then EXIT MOV $M_RT.$M_MSG_NUM,0 ;;AN000;; Reset message number to null RET ;;AN000;; Return ;; $M_DISPLAY_MESSAGE ENDP ;;AN000;; IF NOT COMR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_EXT_PAR_REPLACE ;; ;; FUNCTION: ;; INPUTS: ;; OUPUTS: ;; ;; REGS USED: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_EXT_PAR_REPLACE PROC NEAR ;;AN000;; ;; XOR DX,DX ;;AN000;; Prepare for get binary value (HIGH) MOV AX,$M_RT.$M_MSG_NUM ;;AN000;; Prepare for get binary value (LOW) MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; Set default divisor ;; CALL $M_CONVERT2ASC ;;AN000;; ;; $DO ;;AN000;; POP AX ;;AN000;; Get character in register MOV BYTE PTR $M_RT.$M_TEMP_BUF[BX],AL ;;AN000;; Move char into the buffer INC BX ;;AN000;; Increase buffer count CMP BX,$M_TEMP_BUF_SZ ;;AN000;; Is buffer full? $IF E ;;AN000;; Yes, CALL $M_FLUSH_BUF ;;AN000;; Flush the buffer $ENDIF ;;AN000;; DEC CL ;;AN000;; Have we completed replace? $ENDDO Z ;;AN000;; ;; MOV AX,$M_CR_LF ;;AN000;; Move char into the buffer MOV WORD PTR $M_RT.$M_TEMP_BUF[BX],AX ;;AN000;; Move char into the buffer INC BX ;;AN000;; Increase buffer count INC BX ;;AN000;; Increase buffer count CALL $M_FLUSH_BUF ;;AN000;; Flush the buffer RET ;;AN000:: ;; $M_EXT_PAR_REPLACE ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF IF $M_SUBS ;;AN000;; Include the common subroutines if they haven't yet $M_SUBS = FALSE ;;AN000;; No, then include and reset the flag ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_GET_MSG_ADDRESS ;; ;; FUNCTION: To scan thru classes to return pointer to the message header ;; INPUTS: Access to $M_RES_ADDRESSES ;; OUPUTS: IF CX = 0 THEN Message was not found ;; IF CX > 1 THEN DS:SI points to the specified message ;; REGS CHANGED: ES,DI,CX,DS,SI ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IF FARmsg ;;AN000;; $M_GET_MSG_ADDRESS PROC FAR ;;AN000;; ELSE ;;AN000;; $M_GET_MSG_ADDRESS PROC NEAR ;;AN000;; ENDIF ;;AN000;; ;; PUSH SI ;;AN000;; PUSH BX ;;AN000;; XOR SI,SI ;;AN000;; Use SI as an index XOR CX,CX ;;AN000;; Use CX as an size $DO ;;AN000;; CMP DH,UTILITY_MSG_CLASS ;;AN000;; Were utility messages requested? $IF E ;;AN000;; Yes, IF FARmsg ;;AN000;; LES DI,DWORD PTR $M_RT.$M_CLASS_ADDRS[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; ELSE ;;AN000;; MOV DI,WORD PTR $M_RT.$M_CLASS_ADDRS[SI] ;;AN000;; Get address of class MOV BX,DI ;;AN000; ENDIF ;;AN000;; $ELSE ;;AN000;; No, TEST DH,PARSE_ERR_CLASS ;;AN000;; Were parse errors requested? $IF NE ;;AN000;; Yes, LES DI,DWORD PTR $M_RT.$M_PARSE_COMMAND[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; $ELSE ;;AN000;; No, extended errors were specified CMP AX,$M_CRIT_LO ;;AN000;; Is this a critical error? $IF AE,AND ;;AN000;; CMP AX,$M_CRIT_HI ;;AN000;; $IF BE ;;AN000;; Yes, LES DI,DWORD PTR $M_RT.$M_CRIT_ADDRS[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; $ELSE ;;AN000;; LES DI,DWORD PTR $M_RT.$M_EXT_ERR_ADDRS[SI] ;;AN000;; Get address of class MOV BX,ES ;;AN000; $ENDIF ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; CMP BX,$M_TERMINATING_FLAG ;;AN000;; Are we finished all classes? $IF E ;;AN000;; Yes, CMP DH,UTILITY_MSG_CLASS ;;AN000;; Was it a UTILITY class? $IF E ;;AN000;; Yes, STC ;;AN000;; Set the carry flag $ELSE ;;AN000;; No, MOV $M_RT.$M_MSG_NUM,AX ;;AN000;; Save message number MOV AX,$M_SPECIAL_MSG_NUM ;;AN000;; Set special message number MOV BP,$M_ONE_REPLACE ;;AN000;; Set one replace in message XOR SI,SI ;;AN000;; Reset the SI index to start again CLC ;;AN000;; $ENDIF ;;AN000;; No, $ELSE ;;AN000;; CMP BX,$M_CLASS_NOT_EXIST ;;AN000;; Does this class exist? $IF NE ;;AN001;; Yes, CALL $M_FIND_SPECIFIED_MSG ;;AN000;; Try to find the message $ENDIF ;;AN000;; ADD SI,$M_ADDR_SZ_FAR ;;AN000;; Get next class CLC ;;AN000;; $ENDIF ;;AN000;; $LEAVE C ;;AN000;; OR CX,CX ;;AN000;; Was the message found? $ENDDO NZ,LONG ;;AN000;; PUSHF ;;AN006;; Save the flag state CMP DH,EXT_ERR_CLASS ;;AN006;; Was an extended error requested? $IF E ;;AN006;; Yes, PUSH DX ;;AN006;; Save all needed registers PUSH BP ;;AN006;; PUSH CX ;;AN006;; PUSH ES ;;AN006;; PUSH DI ;;AN006;; PUSH AX ;;AN006;; MOV AX,IFSFUNC_INSTALL_CHECK ;;AN006;; Check if IFSFUNC is installed INT 2FH ;;AN006;; CMP AL,IFSFUNC_INSTALLED ;;AN006;; Is it installed? POP AX ;;AN006;; Restore msg number $IF E ;;AN006;; Yes, MOV BX,AX ;;AN006;; BX is the extended error number MOV AX,IFS_GET_ERR_TEXT ;;AN006;; AX is the muliplex number INT 2FH ;;AN006;; Call IFSFUNC $ELSE ;;AN006;; No, STC ;;AN006;; Carry conditon $ENDIF ;;AN006;; $IF C ;;AN006;; Was there an update? POP DI ;;AN006;; No, POP ES ;;AN006;; Restore old pointer POP CX ;;AN006;; $ELSE ;;AN006;; Yes ADD SP,6 ;;AN006;; Throw away old pointer CALL $M_SET_LEN_IN_CX ;;AN006;; Get the length of the ASCIIZ string $ENDIF ;;AN006;; POP BP ;;AN006;; Restore other Regs POP DX ;;AN006;; $ENDIF ;;AN006;; $M_POPF ;;AN006;; Restore the flag state POP BX ;;AN000;; POP SI ;;AN000;; RET ;;AN000;; Return ES:DI pointing to the message ;; $M_GET_MSG_ADDRESS ENDP ;; ;; $M_SET_LEN_IN_CX PROC NEAR ;; ;; PUSH DI ;;AN006;; Save position PUSH AX ;;AN006;; MOV CX,-1 ;;AN006;; Set CX for decrements XOR AL,AL ;;AN006;; Prepare compare register REPNE SCASB ;;AN006;; Scan for zero NOT CX ;;AN006;; Change decrement into number DEC CX ;;AN006;; Don't include the zero POP AX ;;AN006;; POP DI ;;AN006;; Restore position RET ;;AN006;; ;; $M_SET_LEN_IN_CX ENDP ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_FIND_SPECIFIED_MSG ;; ;; FUNCTION: To scan thru message headers until message is found ;; INPUTS: ES:DI points to beginning of msg headers ;; CX contains the number of messages in class ;; DH contains the message class ;; OUPUTS: IF CX = 0 THEN Message was not found ;; IF CX > 1 THEN ES:DI points to header of specified message ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_FIND_SPECIFIED_MSG PROC NEAR ;;AN000;; ;; CMP BX,1 ;;AN004;; Do we have an address to CALL? $IF E,AND ;;AN004;; Yes, CMP WORD PTR $M_RT.$M_DISK_PROC_ADDR,-1 ;;AN004;; Do we have an address to CALL? $IF NE ;;AN004;; Yes, CMP AX,$M_SPECIAL_MSG_NUM ;;AN004;; Are we displaying a default Ext Err? $IF E ;;AN004;; . . . and . . . PUSH AX ;;AN004;; Reset the special message number MOV AX,$M_RT.$M_MSG_NUM ;;AN004;; Get the old message number CALL DWORD PTR $M_RT.$M_DISK_PROC_ADDR ;;AN004;; Call the READ_DISK_PROC to get error text POP AX ;;AN004;; Reset the special message number $ELSE ;;AN004;; Get the old message number CALL DWORD PTR $M_RT.$M_DISK_PROC_ADDR ;;AN004;; Call the READ_DISK_PROC to get error text $ENDIF ;;AN004;; Get the old message number $ELSE ;;AN004;; XOR CX,CX ;;AN002;; CX = 0 will allow us to CMP DH,UTILITY_MSG_CLASS ;;AN001;; $IF NE ;;AN001;; MOV CL,BYTE PTR ES:[DI].$M_NUM_CLS_MSG ;;AN001;; Get number of messages in class $ELSE ;;AN001;; IF FARmsg ;;AN001;; CMP BYTE PTR ES:[DI].$M_CLASS_ID,DH ;;AN002;; Check if class still exists at ELSE CMP BYTE PTR CS:[DI].$M_CLASS_ID,DH ;;AN002;; Check if class still exists at ENDIF $IF E ;;AN002;; pointer (hopefully) IF FARmsg ;;AN001;; MOV CL,BYTE PTR ES:[DI].$M_NUM_CLS_MSG ;;AN000;; Get number of messages in class ELSE MOV CL,BYTE PTR CS:[DI].$M_NUM_CLS_MSG ;;AN000;; Get number of messages in class ENDIF $ENDIF ;;AN002;; go on to the next class $ENDIF ;;AN001;; ADD DI,$M_CLASS_ID_SZ ;;AN000;; Point past the class header STC ;;AN004;; Flag that we haven't found anything yet $ENDIF ;;AN004;; $IF C ;;AN004;; Have we found anything yet? CLC ;;AN004;; No, reset carry $SEARCH ;;AN000;; OR CX,CX ;;AN000;; Do we have any to check? $LEAVE Z ;;AN000;; No, return with CX = 0 CMP DH,UTILITY_MSG_CLASS ;;AN001;; $IF NE ;;AN001;; CMP AX,WORD PTR ES:[DI].$M_NUM ;;AN001;; Is this the message requested? $ELSE ;;AN001;; IF FARmsg ;;AN001;; CMP AX,WORD PTR ES:[DI].$M_NUM ;;AN000;; Is this the message requested? ELSE CMP AX,WORD PTR CS:[DI].$M_NUM ;;AN000;; Is this the message requested? ENDIF $ENDIF $EXITIF E ;;AN000;; $ORELSE ;;AN000; DEC CX ;;AN000;; No, well do we have more to check? $LEAVE Z ;;AN000;; No, return with CX = 0 ADD DI,$M_ID_SZ ;;AN000;; Yes, skip past msg header $ENDLOOP ;;AN000;; STC ;;AN000;; $ENDSRCH ;;AN000;; Check next message $IF NC ;;AN000;; Did we find the message? CMP DH,UTILITY_MSG_CLASS ;;AN001;; Yes, is it a utility message? CLC ;;AN001;; $IF E ;;AN001;; IF FARmsg ;;AN001;; ELSE ;;AN000;; PUSH CS ;;AN000;; POP ES ;;AN000;; Return ES:DI pointing to the message ENDIF $ENDIF ;;AN001;; ADD DI,WORD PTR ES:[DI].$M_TXT_PTR ;;AN000;; Prepare ES:DI pointing to the message $ENDIF ;;AN004;; $ENDIF ;;AN004;; ;; Yes, great we can return with CX > 0 $IF NC ;;AN000;; Did we find the message? XOR CH,CH ;;AN000;; MOV CL,BYTE PTR ES:[DI] ;;AN000;; Move size into CX INC DI ;;AN000;; Increment past length $ENDIF ;;AN004;; MOV $M_RT.$M_SIZE,$M_NULL ;;AN004;; Reset variable RET ;;AN000;; Return ;; $M_FIND_SPECIFIED_MSG ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of common subroutines ; IF $M_REPLACE ;;AN000;; Is the request to include the code for replaceable parms $M_REPLACE = FALSE ;;AN000;; Tell the assembler we did ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $M_DISPLAY_REPLACE PROC NEAR ;;AN000;; ;; XOR BX,BX ;;AN000;; Use BX for buffer count IF NOT COMR CMP $M_SL.$M_S_ID,$M_SPECIAL_CASE-30H ;;AN000;; Is this the special case (convert to ASCII) $IF E ;;AN000;; Yes, MOV WORD PTR $M_RT.$M_TEMP_BUF[BX],$M_SPACE_HYP ;;AN000;; Move in a " -" INC BX ;;AN000;; Increment count INC BX ;;AN000;; Increment count MOV BYTE PTR $M_RT.$M_TEMP_BUF[BX],$M_SPACE ;;AN000;; Move in a " " INC BX ;;AN000;; Increment count CALL $M_FLUSH_BUF ;;AN000;; Write out " - " to prepare for special case $ENDIF ;;AN000;; If it fails we will catch it later ENDIF POP BP ;;AN000;; Remember the return address XOR BX,BX ;;AN000;; Use BX for buffer count XOR DX,DX ;;AN000;; Use DX for count of parms taken off the stack MOV $M_RT.$M_SIZE,CL ;;AN000;; Save size to later clear stack MOV AL,BYTE PTR $M_SL.$M_S_MINW ;;AN000;; Get the minimum width ;; CMP AL,CL ;;AN000;; Do we need pad chars added? $IF A ;;AN000;; Yes, SUB AL,CL ;;AN000;; Calculate how many pad chars are needed. MOV DH,AL ;;AN000;; Save the number of pad characters TEST BYTE PTR $M_SL.$M_S_FLAG,Right_Align ;;AN000;; Was replaceable parm to be right aligned? $IF NZ ;;AN000;; Yes, $DO ;;AN000;; Begin filling buffer with pad chars MOV AL,BYTE PTR $M_SL.$M_S_PAD ;;AN000;; MOV BYTE PTR $M_RT.$M_TEMP_BUF[BX],AL ;;AN000;; Move in a pad char INC BX ;;AN000;; CMP BX,$M_TEMP_BUF_SZ ;;AN000;; Is buffer full? $IF E ;;AN000;; Yes, CALL $M_FLUSH_BUF ;;AN000;; Flush the buffer $ENDIF ;;AN000;; DEC DH ;;AN000;; Have we filled with enough pad chars? $ENDDO Z ;;AN000;; No, next pad character $ENDIF ;;AN000;; $ENDIF ;;AN000;; Yes, ;; CMP BYTE PTR $M_SL.$M_S_MAXW,$M_UNLIM_W ;;AN000;; Is maximum width unlimited? $IF NE ;;AN000;; CMP BYTE PTR $M_SL.$M_S_MAXW,CL ;;AN000;; Will we exceed maximum width? $IF B ;;AN000;; Yes, SUB CL,BYTE PTR $M_SL.$M_S_MAXW ;;AN000;; Calculate how many extra chars MOV DL,CL ;;AN000;; Remember how many chars to pop off MOV CL,BYTE PTR $M_SL.$M_S_MAXW ;;AN000;; Set new string length $ENDIF ;;AN000;; $ENDIF ;;AN000;; OR CX,CX ;;AN000;; $IF NZ ;;AN000;; $DO ;;AN000;; Begin filling buffer with string TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Char_Type AND $M_TYPE_MASK ;;AN000;; $IF Z,AND ;;AN000;; TEST $M_SL.$M_S_FLAG,Char_field_ASCIIZ AND $M_SIZE_MASK ; Is this replace a ASCIIZ string? $IF NZ ;;AN000;; Yes, MOV AL,BYTE PTR ES:[DI] ;;AN000;; Get first character from string INC DI ;;AN000;; Next character in string $ELSE ;;AN000;; No, POP AX ;;AN000;; Get character in register $ENDIF ;;AN000;; MOV BYTE PTR $M_RT.$M_TEMP_BUF[BX],AL ;;AN000;; Move char into the buffer INC BX ;;AN000;; Increase buffer count CMP BX,$M_TEMP_BUF_SZ ;;AN000;; Is buffer full? $IF E ;;AN000;; Yes, CALL $M_FLUSH_BUF ;;AN000;; Flush the buffer $ENDIF ;;AN000;; DEC CL ;;AN000;; Have we completed replace? $ENDDO Z ;;AN000;; Test again $ENDIF ;;AN000;; ;; TEST BYTE PTR $M_SL.$M_S_FLAG,Right_Align ;;AN000;; Was replaceable parm to be left aligned? $IF Z ;;AN000;; Yes, OR DH,DH ;;AN000;; Do we need pad chars added? $IF NZ ;;AN000;; Yes, $DO ;;AN000;; Begin filling buffer with pad chars MOV AL,BYTE PTR $M_SL.$M_S_PAD ;;AN000;; MOV BYTE PTR $M_RT.$M_TEMP_BUF[BX],AL ;;AN000;; Move in a pad char INC BX ;;AN000;; CMP BX,$M_TEMP_BUF_SZ ;;AN000;; Is buffer full? $IF E ;;AN000;; Yes, CALL $M_FLUSH_BUF ;;AN000;; Flush the buffer $ENDIF ;;AN000;; DEC DH ;;AN000;; Have we filled with enough pad chars? $ENDDO Z ;;AN000;; Test again $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; TEST BYTE PTR $M_SL.$M_S_FLAG,NOT Char_Type AND $M_TYPE_MASK ;;AN000;; $IF Z,AND ;;AN000;; TEST $M_SL.$M_S_FLAG,Char_field_ASCIIZ AND $M_SIZE_MASK ;;AN000;; Is this replace a ASCIIZ string? $IF NZ ;;AN000;; Yes, $ELSE ;;AN000;; OR DL,DL ;;AN000;; $IF NE ;;AN000;; $DO ;;AN000;; POP [$M_RT.$M_RETURN_ADDR] ;;AN000;; Clean Up stack using spare variable DEC DL ;;AN000;; Are we done? $ENDDO Z ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; CALL $M_FLUSH_BUF ;;AN000;; Flush the buffer for the final time PUSH BP ;;AN000;; Restore the return address ;; RET ;;AN000;; ;; $M_DISPLAY_REPLACE ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_FLUSH_BUFFER ;; ;; FUNCTION: Display the contents of the temporary buffer ;; INPUTS: DI contains the number of bytes to display ;; OUTPUTS: BX reset to zero ;; ;; REGS USED: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_FLUSH_BUF PROC NEAR ;;AN000;; ;; PUSH CX ;;AN000;; Save changed regs PUSH ES ;;AN000;; PUSH DI ;;AN000;; PUSH DS ;;AN000;; Set ES pointing to buffer POP ES ;;AN000;; ;; MOV CX,BX ;;AN000;; Set number of bytes to display XOR BX,BX ;;AN000;; Reset buffer counter LEA DI,$M_RT.$M_TEMP_BUF ;;AN000;; Reset buffer location pointer CALL $M_DISPLAY_STRING ;;AN000;; Display the buffer ;; $IF NC ;;AN000;; Error? POP DI ;;AN000;; No, Restore changed regs POP ES ;;AN000;; POP CX ;;AN000;; $ELSE ;;AN000;; Yes, ADD SP,6 ;;AN000;; Fix stack STC ;;AN000;; $ENDIF ;;AN000;; Error? ;; RET ;;AN000;; Return ;; $M_FLUSH_BUF ENDP ;;AN000;; ;; ;; IF CHARmsg ;;AN000;; Is the request to include the code for CHAR replace? $M_REPLACE = TRUE ;;AN000;; Yes, THEN include it and flag that we will need common $M_CHAR_ONLY = TRUE ;;AN000;; replacement code later ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_CHAR_REPLACE ;; ;; FUNCTION: Will prepare a single char or ASCIIZ string for replace ;; INPUTS: DS:SI points at corresponding SUBLIST ;; ES:DI contains the VALUE from SUBLIST ;; OUTPUTS: CX contains number of characters on stack ;; Top of stack --> Last character ;; . . . ;; Bot of stack --> First character ;; ;; OTHER REGS Revised: AX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_CHAR_REPLACE PROC NEAR ;;AN000;; ;; POP BP ;;AN000;; Save return address TEST $M_SL.$M_S_FLAG,NOT Char_Field_Char AND $M_SIZE_MASK ;;AN000;; Was Character specified? $IF Z ;;AN000;; Yes, MOV AL,BYTE PTR ES:[DI] ;;AN000;; Get the character PUSH AX ;;AN000;; Put it on the stack INC CX ;;AN000;; Increase the count CALL $M_IS_IT_DBCS ;;AN000;; Is this the first byte of a DB character $IF C ;;AN000;; Yes, MOV AL,BYTE PTR ES:[DI]+1 ;;AN000;; Get the next character PUSH AX ;;AN000;; Put it on the stack CLC ;;AN000;; Clear the carry $ENDIF ;;AN000;; $ELSE ;;AN000;; No, it was an ASCIIZ string $DO ;;AN000;; MOV AL,BYTE PTR ES:[DI] ;;AN000;; Get the character OR AL,AL ;;AN000;; Is it the NULL? $LEAVE Z ;;AN000;; No, INC DI ;;AN000;; Next character INC CX ;;AN000;; Increment the count $ENDDO ;;AN000;; Yes, SUB DI,CX ;;AN000;; Set SI at the beginning of the string $ENDIF ;;AN000;; ;;AN000;; PUSH BP ;;AN000;; Restore return address RET ;;AN000;; Return ;; $M_CHAR_REPLACE ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of CHAR replace code ; IF NUMmsg ;;AN000;; Is the request to include the code for NUM replace? $M_REPLACE = TRUE ;;AN000;; Yes, THEN include it and flag that we will need common $M_CHAR_ONLY = FALSE ;;AN000;; replacement code later ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_BIN2ASC_REPLACE ;; ;; FUNCTION: Convert a signed or unsigned binary number to an ASCII string ;; and prepare to display ;; INPUTS: DS:SI points at corresponding SUBLIST ;; ES:DI contains the VALUE from SUBLIST ;; OUTPUTS: CX contains number of characters on stack ;; Top of stack --> Last character ;; . . . ;; Bot of stack --> First character ;; OTHER REGS Revised: BX,DX,AX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_BIN2ASC_REPLACE PROC NEAR ;;AN000;; ;; POP BP ;;AN000;; Save return address ;; XOR DX,DX ;;AN000;; Prepare for get binary value (HIGH) XOR AX,AX ;;AN000;; Prepare for get binary value (LOW) MOV $M_RT.$M_DIVISOR,$M_BASE16 ;;AN000;; Set default divisor XOR BX,BX ;;AN000;; Use BP as the NEG flag (if applicable) IF NOT COMR TEST $M_SL.$M_S_FLAG,NOT $M_BYTE AND $M_SIZE_MASK ;;AN000;; Was BYTE specified? $IF Z ;;AN000;; MOV AL, BYTE PTR ES:[DI] ;;AN000;; Setup byte in AL TEST $M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; Was Signed binary specified? $IF Z ;;AN000;; TEST AL,10000000b ;;AN000;; Is this number negative? $IF NZ ;;AN000;; Yes, INC BX ;;AN000;; Remember that it was negative AND AL,01111111b ;;AN000;; Make it positive $ENDIF ;;AN000;; MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; $ENDIF ;;AN000;; TEST $M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; Was Signed binary specified? $IF Z ;;AN000;; MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; $ENDIF ;;AN000;; $ELSE ;;AN000;; ENDIF TEST $M_SL.$M_S_FLAG,NOT $M_WORD AND $M_SIZE_MASK ;;AN000;; Was WORD specified? $IF Z ;;AN000;; MOV AX, WORD PTR ES:[DI] ;;AN000;; Setup byte in AL TEST $M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK ;; AN000;; Was Signed binary specified? $IF Z ;;AN000;; TEST AH,10000000b ;;AN000;; Is this number negative? $IF NZ ;;AN000;; Yes, INC BX ;;AN000;; Remember that it was negative AND AH,01111111b ;;AN000;; Make it positive $ENDIF ;;AN000;; MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; $ENDIF ;;AN000;; TEST $M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; Was Signed binary specified? $IF Z ;;AN000;; MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; $ENDIF ;;AN000;; $ELSE ;;AN000;; IF NOT COMR MOV AX, WORD PTR ES:[DI] ;;AN000;; Setup Double word in DX:AX MOV DX, WORD PTR ES:[DI]+2 ;;AN000;; TEST $M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; Was Signed binary specified? $IF Z ;;AN000;; TEST DH,10000000b ;;AN000;; Is this number negative? $IF NZ ;;AN000;; Yes, INC BX ;;AN000;; Remember that it was negative AND DH,01111111b ;;AN000;; Make it positive $ENDIF ;;AN000;; MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; $ENDIF ;;AN000;; TEST $M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK ;;AN000;; Was Signed binary specified? $IF Z ;;AN000;; MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; $ENDIF ;;AN000;; ENDIF $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; CALL $M_CONVERT2ASC ;;AN000;; Convert to ASCII string IF NOT COMR OR BX,BX ;;AN000;; $IF NZ ;;AN000;; Was number negative? XOR DX,DX ;;AN000;; Yes, MOV DL,$M_NEG_SIGN ;;AN000;; Put "-" on the stack with the number PUSH DX ;;AN000;; $ENDIF ;;AN000;; No, ENDIF ;; PUSH BP ;;AN000;; Restore return address RET ;;AN000;; Return ;; $M_BIN2ASC_REPLACE ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of NUM replace code ; IF DATEmsg ;;AN000;; Is the request to include the code for DATE replace? $M_REPLACE = TRUE ;;AN000;; Yes, THEN include it and flag that we will need common $M_CHAR_ONLY = FALSE ;;AN000;; replacement code later ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_DATE_REPLACE ;; ;; FUNCTION: Convert a date to a decimal ASCII string using current ;; country format and prepare to display ;; INPUTS: DS:SI points at corresponding SUBLIST ;; ES:DI points at VALUE from SUBLIST ;; OUTPUTS: CX contains number of characters on stack ;; Top of stack --> Last character ;; . . . ;; Bot of stack --> First character ;; OTHER REGS Revised: DX, AX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_DATE_REPLACE PROC NEAR ;;AN000;; ;; POP BP ;;AN000;; Save return address MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; Set default divisor CALL $M_GET_DATE ;;AN000;; Set date format/separator in $M_RT ;;AN000;; All O.K.? XOR DX,DX ;;AN000;; Reset DX value XOR AX,AX ;;AN000;; Reset AX value CMP WORD PTR $M_RT.$M_DATE_FORMAT,0 ;;AN000;; USA Date Format $IF E ;;AN000;; Beginning from end: (saved on the stack) CALL $M_YEAR ;;AN000;; Get Year CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string PUSH WORD PTR $M_RT.$M_DATE_SEPARA ;;AN000;; INC CX ;;AN000;; Increment count XOR AX,AX ;;AN000;; Reset AX value MOV AL,BYTE PTR $M_SL.$M_S_VALUE+3 ;;AN000;; Get Day CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string PUSH WORD PTR $M_RT.$M_DATE_SEPARA ;;AN000;; INC CX ;;AN000;; Increment count MOV AL,BYTE PTR $M_SL.$M_S_VALUE+2 ;;AN000;; Get Month CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string $ENDIF ;;AN000;; ;; CMP WORD PTR $M_RT.$M_DATE_FORMAT,1 ;;AN000;; EUROPE Date Format $IF E ;;AN000;; Beginning from end: (saved on the stack) CALL $M_YEAR ;;AN000;; Get Year CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string PUSH WORD PTR $M_RT.$M_DATE_SEPARA ;;AN000;; INC CX ;;AN000;; XOR AX,AX ;;AN000;; Reset AX MOV AL,BYTE PTR $M_SL.$M_S_VALUE+2 ;;AN000;; Get Month CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string PUSH WORD PTR $M_RT.$M_DATE_SEPARA ;;AN000;; INC CX ;;AN000;; MOV AL,BYTE PTR $M_SL.$M_S_VALUE+3 ;;AN000;; Get Day CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string $ENDIF ;;AN000;; ;; CMP WORD PTR $M_RT.$M_DATE_FORMAT,2 ;;AN000;; JAPAN Date Format $IF E ;;AN000;; Beginning from end: (saved on the stack) MOV AL,BYTE PTR $M_SL.$M_S_VALUE+3 ;;AN000;; Get Day CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string PUSH WORD PTR $M_RT.$M_DATE_SEPARA ;;AN000;; INC CX ;;AN000;; MOV AL,BYTE PTR $M_SL.$M_S_VALUE+2 ;;AN000;; Get Month CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string PUSH WORD PTR $M_RT.$M_DATE_SEPARA ;;AN000;; INC CX ;;AN000;; CALL $M_YEAR ;;AN000;; Get Year CALL $M_CONVERTDATE ;;AN000;; Convert it to an ASCII string $ENDIF ;;AN000;; ;; PUSH BP ;;AN000;; Restore return address RET ;;AN000;; Return ;; $M_DATE_REPLACE ENDP ;;AN000;; ;; $M_GET_DATE PROC NEAR ;;AN000;; MOV AH,DOS_GET_COUNTRY ;;AN000;; Call DOS for country dependant info MOV AL,0 ;;AN000;; Get current country info LEA DX,$M_RT.$M_TEMP_BUF ;;AN000;; Set up addressibility to buffer INT 21H ;;AN000;; $IF C ;;AN000;; No, MOV WORD PTR $M_RT.$M_DATE_FORMAT,$M_DEF_DATE_FORM ;;AN000;; Set default date format (BH) MOV BYTE PTR $M_RT.$M_DATE_SEPARA,$M_DEF_DATE_SEP ;;AN000;; Set default date separator (BL) $ENDIF ;;AN000;; RET ;;AN000;; $M_GET_DATE ENDP ;;AN000;; ;; $M_YEAR PROC NEAR ;;AN000;; MOV AX,WORD PTR $M_SL.$M_S_VALUE ;;AN000;; Get Year TEST $M_SL.$M_S_FLAG,Date_MDY_4 AND $M_DATE_MASK ;;AN000;; Was Month/Day/Year (2 Digits) specified? $IF Z ;;AN000;; CMP AX,$M_MAX_2_YEAR ;;AN000;; Get Year $IF A ;;AN000;; MOV AX,$M_MAX_2_YEAR ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; RET ;;AN000;; $M_YEAR ENDP ;;AN000;; ;; $M_CONVERTDATE PROC NEAR ;;AN000;; POP WORD PTR $M_RT.$M_TEMP_BUF ;;AN000;; Save return address MOV $M_RT.$M_SIZE,CL ;;AN000;; Save the size before conversion CALL $M_CONVERT2ASC ;;AN000;; Convert it to an ASCII string DEC CX ;;AN000;; Test if size only grew by 1 CMP CL,$M_RT.$M_SIZE ;;AN000;; Did size only grow by one $IF E ;;AN000;; Yes, MOV AX,$M_TIMEDATE_PAD ;;AN000;; Get a pad character (0) PUSH AX ;;AN000;; Save it INC CX ;;AN000;; Count it $ENDIF ;;AN000;; INC CX ;;AN000;; Restore CX PUSH WORD PTR $M_RT.$M_TEMP_BUF ;;AN000;; Save return address RET ;;AN000;; $M_CONVERTDATE ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of DATE replace code ; IF TIMEmsg ;;AN000;; Is the request to include the code for TIME replace? $M_REPLACE = TRUE ;;AN000;; Yes, THEN include it and flag that we will need common $M_CHAR_ONLY = FALSE ;;AN000;; replacement code later ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_TIME_REPLACE ;; ;; FUNCTION: Convert a time to a decimal ASCII string ;; and prepare to display ;; INPUTS: DS:SI points at corresponding SUBLIST ;; ES:DI points at VALUE from SUBLIST ;; OUTPUTS: CX contains number of characters on stack ;; Top of stack --> Last character ;; . . . ;; Bot of stack --> First character ;; REGS USED: BP,CX,AX ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_TIME_REPLACE PROC NEAR ;;AN000;; ;; POP BP ;;AN000;; Save return address MOV $M_RT.$M_DIVISOR,$M_BASE10 ;;AN000;; Set default divisor CALL $M_GET_TIME ;;AN000;; All O.K.? TEST $M_SL.$M_S_FLAG,Time_Cty_Type AND $M_TIME_MASK ;;AN000;; Is this a request for current country info? $IF NZ ;;AN000;; Yes, CMP BYTE PTR $M_RT.$M_TIME_FORMAT,0 ;;AN000;; Is the current country format 12 Hour? $IF E ;;AN000;; Yes, MOV AL,BYTE PTR $M_SL.$M_S_VALUE ;;AN000;; Get Hours CMP AL,12 ;;AN000;; Is hour 12 or less? $IF L,OR ;;AN000;; or CMP AL,23 ;;AN000;; Is hour 24 or greater? $IF G ;;AN000;; Yes, MOV AL,$M_AM ;;AN000;; PUSH AX ;;AN000;; Push an "a" to represent AM. INC CX ;;AN000;; $ELSE ;;AN000;; No, MOV AL,$M_PM ;;AN000;; PUSH AX ;;AN000;; Push an "p" to represent PM. INC CX ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; XOR AX,AX ;;AN000;; XOR DX,DX ;;AN000;; TEST $M_SL.$M_S_FLAG,Time_HHMMSSHH_Cty AND $M_SIZE_MASK ;;AN000;; Was Hour/Min/Sec/Hunds (12 Hour) specified? $IF NZ ;;AN000;; MOV AL,BYTE PTR $M_SL.$M_S_VALUE+3 ;;AN000;; Get Hundreds CALL $M_CONVERTTIME ;;AN000;; PUSH WORD PTR $M_RT.$M_DECI_SEPARA ;;AN000;; INC CX ;;AN000;; $ENDIF ;;AN000;; TEST $M_SL.$M_S_FLAG,Time_HHMMSSHH_Cty AND $M_SIZE_MASK ;;AN000;; Was Hour/Min/Sec/Hunds (12 Hour) specified? $IF NZ,OR ;;AN000;; TEST $M_SL.$M_S_FLAG,Time_HHMMSS_Cty AND $M_SIZE_MASK ;;AN000;; Was Hour/Min/Sec (12 Hour) specified? $IF NZ ;;AN000;; MOV AL,BYTE PTR $M_SL.$M_S_VALUE+2 ;;AN000;; Get Seconds CALL $M_CONVERTTIME ;;AN000;; PUSH WORD PTR $M_RT.$M_TIME_SEPARA ;;AN000;; INC CX ;;AN000;; $ENDIF ;;AN000;; ;; Do Hour/Min (12 Hour) MOV AL,BYTE PTR $M_SL.$M_S_VALUE+1 ;;AN000;; Get Minutes CALL $M_CONVERTTIME ;;AN000;; PUSH WORD PTR $M_RT.$M_TIME_SEPARA ;;AN000;; INC CX ;;AN000;; ;; MOV AL,BYTE PTR $M_SL.$M_S_VALUE ;;AN000;; Get Hours TEST $M_SL.$M_S_FLAG,Time_Cty_Type AND $M_TIME_MASK ;;AN000;; Is this a request for current country info? $IF NZ ;;AN000;; Yes, CMP BYTE PTR $M_RT.$M_TIME_FORMAT,0 ;;AN000;; Is the current country format 12 Hour? $IF E ;;AN000;; Yes, CMP AL,13 ;;AN000;; Is hour less than 12? $IF GE ;;AN000;; Yes, SUB AL,12 ;;AN000;; Set to a 12 hour value $ENDIF ;;AN000;; CMP AL,0 ;;AN000;; Is hour less than 12? $IF E ;;AN000;; Yes, MOV AL,12 ;;AN000;; Set to a 12 hour value $ENDIF ;;AN000;; $ENDIF ;;AN000;; $ENDIF ;;AN000;; CALL $M_CONVERT2ASC ;;AN000;; Convert it to ASCII ;; PUSH BP ;;AN000;; Restore return address RET ;;AN000;; Return ;; $M_TIME_REPLACE ENDP ;;AN000;; ;; $M_GET_TIME PROC NEAR ;;AN000;; MOV AH,DOS_GET_COUNTRY ;;AN000;; Call DOS for country dependant info MOV AL,0 ;;AN000;; Get current country info LEA DX,$M_RT.$M_TEMP_BUF ;;AN000;; Set up addressibility to buffer INT 21H ;;AN000;; $IF C ;;AN000;; No, MOV WORD PTR $M_RT.$M_TIME_FORMAT,$M_DEF_TIME_FORM ;;AN000;; Set default time format (BH) MOV BYTE PTR $M_RT.$M_TIME_SEPARA,$M_DEF_TIME_SEP ;;AN000;; Set default time separator (BL) MOV BYTE PTR $M_RT.$M_DECI_SEPARA,$M_DEF_DECI_SEP ;;AN000;; Set default time separator (BL) $ENDIF ;;AN000;; RET ;;AN000;; $M_GET_TIME ENDP ;;AN000;; ;; $M_CONVERTTIME PROC NEAR ;;AN000;; POP WORD PTR $M_RT.$M_TEMP_BUF ;;AN000;; Save return address MOV $M_RT.$M_SIZE,CL ;;AN000;; Save the size before conversion CALL $M_CONVERT2ASC ;;AN000;; Convert it to an ASCII string DEC CX ;;AN000;; Test if size only grew by 1 CMP CL,$M_RT.$M_SIZE ;;AN000;; Did size only grow by one $IF E ;;AN000;; Yes, MOV AX,$M_TIMEDATE_PAD ;;AN000;; Get a pad character (0) PUSH AX ;;AN000;; Save it INC CX ;;AN000;; Count it $ENDIF ;;AN000;; INC CX ;;AN000;; Restore CX PUSH WORD PTR $M_RT.$M_TEMP_BUF ;;AN000;; Save return address RET ;;AN000;; $M_CONVERTTIME ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of TIME replace ENDIF ;;AN000;; END of include of Replacement common code ; IF INPUTmsg ;;AN000;; Is the request to include the code for NUM replace? INPUTmsg = FALSE ;;AN000;; Yes, THEN include it and reset the flag ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PROC NAME: $M_WAIT_FOR_INPUT ;; ;; FUNCTION: To accept keyed input and return extended key value ;; in AX register ;; INPUTS: DL contains the DOS function requested for input ;; OUPUTS: AX contains the extended key value that was read ;; REGS USED: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; $M_WAIT_FOR_INPUT PROC NEAR ;;AN000;; ;; PUSH CX ;;AN000;; Save CX PUSH DX ;;AN000;; Save DX PUSH DS ;;AN000;; Save Data segment ;; CMP DL,DOS_CLR_KEYB_BUF_MASK ;;AN001;; Are we to clear the keyboard buffer? $IF A ;;AN001;; Yes, MOV AL,DL ;;AN001;; Mov function into AL AND AL,LOW_NIB_MASK ;;AN001;; Mask out the C in high nibble MOV AH,DOS_CLR_KEYB_BUF ;;AN001;; Set input function $ELSE ;;AN001;; No, MOV AH,DL ;;AN000;; Put DOS function in AH $ENDIF ;;AN001;; PUSH ES ;;AN000;; Get output buffer segment POP DS ;;AN000;; MOV DX,DI ;;AN000;; Get output buffer offset in case needed INT 21H ;;AN000;; Get keyboard input POP DS ;;AN000;; CMP DL,DOS_BUF_KEYB_INP ;;AN000;; CLC ;;AN000;; $IF NE ;;AN000;; If character input CALL $M_IS_IT_DBCS ;;AN000;; Is this character DBCS? $IF C ;;AN000;; MOV CL,AL ;;AN000;; Save first character MOV AH,DL ;;AN001;; Get back function INT 21H ;;AN000;; Get keyboard input MOV AH,CL ;;AN000;; Retreive first character AX = xxxx CLC ;;AN000;; Clear carry condition $ELSE ;;AN000;; MOV AH,0 ;;AN000;; AX = 00xx where xx is SBCS $ENDIF ;;AN000;; $ENDIF ;;AN000;; ;; $IF NC ;;AN000;; POP DX ;;AN000;; POP CX ;;AN000;; $ELSE ;;AN000;; ADD SP,4 ;;AN000;; STC ;;AN000;; Reset carry flag $ENDIF ;;AN000;; RET ;;AN000;; Return ;; $M_WAIT_FOR_INPUT ENDP ;;AN000;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDIF ;;AN000;; END of include of Wait for Input ENDIF ;;AN000;; END of include of SYSDISPMSG ENDIF ;;AN000;; END of include of MSG_DATA_ONLY ENDIF ;;AN000;; END of include of Structure only