[Back to DATETIME SWAG index] [Back to Main SWAG index] [Original]
{ COUNTRY.PAS -- Going native with Dos. Do not use under DOS 2.xx.
Written by Wilbert van Leijen and released into the Public Domain }
Unit Country;
Interface
uses Dos;
Type
DelimType = Record
thousands,
decimal,
date,
time : Array[0..1] of Char;
end;
CurrType = (leads, { symbol precedes value }
trails, { value precedes symbol }
leads_, { symbol, space, value }
_trails, { value, space, symbol }
replace); { replaced }
CountryType = Record
DateFormat : Word; { 0: USA, 1: Europe, 2: Japan }
CurrSymbol : Array[0..4] of Char;
Delimiter : DelimType; { Separators }
CurrFormat : CurrType; { Way currency is formatted }
CurrDigits : Byte; { Digits in currency }
Clock24hrs : Boolean; { True if 24-hour clock }
CaseMapCall : Procedure; { Lookup table for ASCII ò $80 }
DataListSep : Array[0..1] of Char;
CountryCode : Word;
end;
UpCaseType = Function(c : Char) : Char;
UpCaseStrType = Procedure(Var s : String);
Var
UpCase : UpCaseType; { To be determined at runtime }
UpCaseStr : UpCaseStrType;
CountryOk : Boolean; { Could determine country code flag }
CountryRec : CountryType;
Procedure GetSysTime(Var Today : DateTime);
Procedure SetSysTime(Today : DateTime);
Function DateString(FileStamp : DateTime) : String;
Function TimeString(FileStamp : DateTime) : String;
Implementation
{$R-,S-,V- }
{ Country dependent character capitalisation for DOS 3 }
Function UpCase3(c : Char) : Char; Far; Assembler;
ASM
MOV AL, c
CMP AL, 'a'
JB @2
CMP AL, 'z'
JA @1
AND AL, 11011111b
JMP @2
@1: CMP AL, 80h
JB @2
CALL [CountryRec.CaseMapCall]
@2:
end; { UpCase3 }
{ Country dependent string capitalisation for DOS 3 }
Procedure UpCaseStr3(Var s : String); Far; Assembler;
ASM
CLD
LES DI, s
XOR AX, AX
MOV AL, ES:[DI]
STOSB
XCHG AX, CX
JCXZ @4
@1: MOV AL, ES:[DI]
CMP AL, 'a'
JB @3
CMP AL, 'z'
JA @2
AND AL, 11011111b
JMP @3
@2: CMP AL, 80h
JB @3
CALL [CountryRec.CaseMapCall]
@3: STOSB
LOOP @1
@4:
end; { UpCaseStr3 }
{ Country dependent character capitalisation for DOS 4+ }
Function UpCase4(c : Char) : Char; Far; Assembler;
ASM
MOV DL, c
MOV AX, 6520h
INT 21h
MOV AL, DL
end; { UpCase4 }
{ Country dependent string capitalisation for DOS 4+ }
Procedure UpCaseStr4(Var s : String); Far; Assembler;
ASM
PUSH DS
CLD
XOR AX, AX
LDS SI, s
LODSB
XCHG AX, CX
JCXZ @1
MOV DX, SI
MOV AX, 6521h
INT 21h
@1: POP DS
end; { UpCaseStr4 }
{ Return system time in Today }
Procedure GetSysTime(Var Today : DateTime); Assembler;
ASM
LES DI, Today
CLD
MOV AH, 2Ah
INT 21h
XCHG AX, CX { year }
STOSW
XOR AH, AH
MOV AL, DH { month }
STOSW
MOV AL, DL { day }
STOSW
MOV AH, 2Ch
INT 21h
XOR AH, AH
MOV AL, CH { hours }
STOSW
MOV AL, CL { min }
STOSW
MOV AL, DH { seconds }
STOSW
end; { GetSysTime }
{ Set system time }
Procedure SetSysTime(Today : DateTime); Assembler;
ASM
PUSH DS
CLD
LDS SI, Today
LODSW
MOV CX, AX { year }
LODSW
MOV DH, AL { month }
LODSW
MOV DL, AL { day }
MOV AH, 2Bh
INT 21h
LODSW
MOV CH, AL { hour }
LODSW
MOV CL, AL { minutes }
LODSW
MOV DH, AL { seconds }
XOR DL, DL
MOV AH, 2Dh
INT 21h
POP DS
end; { SetSysTime }
{ Convert a binary number to an unpacked decimal
On entry: AL <-- number ó 99
On exit: AX --> ASCII representation }
Procedure UnpackNumber; Assembler;
ASM
AAM
XCHG AH, AL
ADD AX, '00'
end; { UnpackNumber }
Function DateString(FileStamp : DateTime) : String; Assembler;
ASM
PUSH DS
CLD
{ Set string length }
LES DI, @Result
MOV AL, 8
STOSB
{ Store year, month and day in registers }
LDS SI, FileStamp
LODSW
SUB AX, 1900
CALL UnpackNumber
XCHG AX, BX { yy -> BX }
LODSW
CALL UnpackNumber
XCHG AX, CX { mm -> CX }
LODSW
CALL UnpackNumber
XCHG AX, DX { dd -> DX }
{ Case date format of
0 : USA standard mm:dd:yy
1 : Europe standard dd:mm:yy
2 : Japan standard yy:mm:dd }
POP DS
MOV AL, Byte Ptr [CountryRec.DateFormat]
OR AL, AL
JZ @1
DEC AL
JZ @2
{ Japan }
PUSH DX
PUSH CX
PUSH BX
JMP @3
{ USA }
@1: PUSH BX
PUSH DX
PUSH CX
JMP @3
{ Europe }
@2: PUSH BX
PUSH CX
PUSH DX
{ Remove leading zero }
@3: POP AX
CMP AL, '0'
JNE @4
MOV AL, ' '
@4: MOV CL, Byte Ptr [CountryRec.Delimiter.date]
STOSW
MOV AL, CL
STOSB
POP AX
STOSW
MOV AL, CL
STOSB
POP AX
STOSW
end; { DateString }
Function TimeString(FileStamp : DateTime) : String; Assembler;
ASM
PUSH DS
CLD
MOV BL, [CountryRec.Clock24Hrs]
MOV DX, [CountryRec.Delimiter.time]
LDS SI, FileStamp
LES DI, @Result
{ Set string length }
MOV AL, 5
STOSB
{ Advance string index of FileStamp to hour field }
ADD SI, 6
LODSW
{ Query time format }
OR BL, BL
JNZ @2
{ a.m. / p.m. clock format, set string length to 6 }
INC Byte Ptr ES:[DI-1]
MOV BL, 'a'
CMP AL, 12
JBE @1
SUB AL, 12
MOV BL, 'p'
@1: MOV Byte Ptr ES:[DI+5], BL
{ Convert to ASCII and remove leading zero }
@2: CALL UnpackNumber
CMP AL, '0'
JNE @3
MOV AL, ' '
@3: STOSW
{ Write time separator }
XCHG AX, DX
STOSB
{ Store minutes in string }
LODSW
CALL UnpackNumber
STOSW
POP DS
end; { TimeString }
Begin { Country }
ASM
{ Exit if Dos version < 3.0 }
MOV AH, 30h
INT 21h
CMP AL, 3
JB @3
JA @1
{ Initialise pointers to DOS 3 capitalisation routines }
MOV Word Ptr [UpCase], Offset UpCase3
MOV Word Ptr [UpCaseStr], Offset UpCaseStr3
JMP @2
{ Initialise pointers to DOS 4 (or later) capitalisation routines }
@1: MOV Word Ptr [UpCase], Offset UpCase4
MOV Word Ptr [UpCaseStr], Offset UpCaseStr4
@2: MOV Word Ptr [UpCase+2], CS
MOV Word Ptr [UpCaseStr+2], CS
{ Call Dos 'Get country dependent information' function }
MOV AX, 3800h
MOV DX, Offset [CountryRec]
INT 21h
JC @3
{ Add country code to the structure }
MOV [CountryRec.CountryCode], BX
MOV [CountryOk], True
JMP @4
@3: MOV [CountryOk], False
@4:
end;
end. { Country }
[Back to DATETIME SWAG index] [Back to Main SWAG index] [Original]