windows-nt/Source/XPSP1/NT/base/mvdm/dos/v86/inc/msgserv.sa
2020-09-26 16:20:57 +08:00

2629 lines
109 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; * * * * * * * * * * * * 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