windows-nt/Source/XPSP1/NT/base/mvdm/dos/v86/inc/msgserv.sa

2629 lines
109 KiB
Plaintext
Raw Normal View History

2020-09-26 03:20:57 -05:00
; * * * * * * * * * * * * 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