📄 uiutil.asm
字号:
TITLE uiutil.asm - low level utilities for SHELL
;***
;uiutil.asm
;
; Copyright <C> 1985-1988, Microsoft Corporation
;
;Purpose:
; Support routines needed by user-interface.
;
;
;*******************************************************************************
.xlist
include version.inc
.list
include cw/version.inc
include cw/windows.inc
include cw/edityp.inc
IncludeOnce architec
IncludeOnce qbimsgs
IncludeOnce ui
assumes DS,DATA
assumes ES,DATA
assumes SS,DATA
subttl DATA segment definitions.
page
externFP CbSz
DOS_LOGICAL_DRIVE EQU 504H
sBegin DATA
staticB DisketteDrives,-1 ; Number of Diskette Drives on machine
; -1 ==> not yet determined
externW __doserrno
externW iHelpId
externB fMousePresent
sEnd DATA
sBegin UI
assumes CS,UI
externNP MsgBoxPsz
subttl Low level MSDOS File I/O calls.
page
;***
;
; GetCurDrive2()
;
; Returns the current drive letter.
;
; Inputs: none
;
; Outputs: AL is the current drive letter
;
; Uses: AX, DX.
;
;****
cProc GetCurDrive2,<NEAR,PUBLIC>
cBegin
mov ah, 19h
int 21h
add al, 'A'
xor ah, ah
cEnd
;***
;
; GetCurDriveDir(szPath)
;
; Gets the current working directory and drive into the supplied buffer.
; Re-written in assembler and moved here with revision [1].
;
; Inputs:
; szPath = pointer to buffer area. (<=64 bytes long).
;
; Outputs:
; None.
; Uses:
; Per convention.
;
;****
cProc GetCurDriveDir,<NEAR,PUBLIC>,<SI>
parmW szPath
cBegin
cCall GetCurDrive2 ; al = current drive letter
mov si,szPath ;Get pointer to target area.
mov Byte Ptr [si],al ;store drive letter
mov Word Ptr [si+1],'\:' ; store ":\"
add si,3 ;advance past "drive:\"
;We do not have to worry about KANJI characters here, as
;drive designators can only be single byte characters
and al, not 20H ; convert lower case to upper case.
sub al, 'A' - 1 ; 0 -> Current drive, 1 -> A, 2 -> B,...
mov dl,al
mov ah, 47h
int 21h
mov bx, 0
mov [__doserrno],bx
xchg ax,bx
jnc GetCurDriveDir_Exit
mov [__doserrno],bx
dec ax
GetCurDriveDir_Exit:
cEnd
page
;***
;
; SetCurDrive2()
;
; Sets the current drive.
;
; Inputs: letter - is the drive letter.
;
; Outputs: none.
;
; Uses: AX, DX.
;
;****
cProc SetCurDrive2,<NEAR,PUBLIC>
parmB letter
cBegin
mov dl, letter
push dx
cCall CheckSwitchDiskettes,<dx>
pop dx
and dl, not 20H ; convert lower case to upper
sub dl, 'A' ; A->0, B->1, etc
mov ah, 0eH
int 21h
cEnd
;***
;
; SetCurDir2(pArea)
;
; Set's the current working directory from the supplied pointer buffer.
;
; Inputs: pointer to buffer area. <= 64 bytes.
;
; Outputs: AX == 0 for normal completion.
; AX == -1 for error during operation.
;
; Uses: AX, DX.
;
;****
cProc SetCurDir2,<NEAR,PUBLIC>
parmDP pArea
cBegin
xor ax,ax
mov [__doserrno],ax
mov bx, pArea
push bx ; save for later
mov dx,[bx] ; dx = possible drive letter + colon
cmp dh, ':' ; drive specified?
jne NoDriveSpec ; brif not
cCall SetCurDrive2,<dx> ; set current drive
noDriveSpec:
pop dx ; dx = *directory name
mov ah, 3Bh ; set current directory
int 21h
mov bx,0 ; assume success
xchg ax,bx ; ax = return code
jnc SetCurDir_Exit ; brif success, with ax = 0
mov [__doserrno],bx
dec ax ; ax = -1 ==> failure
SetCurDir_Exit:
cEnd
page
;***
;
; CheckSwitchDiskettes( drive )
;
; Inputs: drive - is the drive letter we are about to access
;
; Outputs: none
;
; Uses: all
;
;****
cProc CheckSwitchDiskettes,<NEAR,PUBLIC>
parmB drive
cBegin
mov al,DisketteDrives ; al = # disk drives
cmp al,-1 ; have we initialized it?
jne InitDone ; brif so
int 11H ; BIOS Equipment List
shl ax, 1
shl ax, 1
and ah, 00000011B
inc ah
mov al,ah
mov DisketteDrives, al ; save value for next time
; so we don't have to do the
; INT every time
InitDone: ; al = # disk drives
cmp al, 1
jne EndCheckSwitchDiskettes
mov dl, drive
and dl, not 20H ; convert lower case to upper
sub dl, 'A' ; A->0, B->1, etc
cmp dl, 1
ja EndCheckSwitchDiskettes ; only drives A and B matter
xor ax, ax
mov es, ax
mov al, es:[DOS_LOGICAL_DRIVE] ; Get current logical drive
cmp dl, al
je EndCheckSwitchDiskettes
; Well now we know... We have to switch diskettes.
push es ; save segment 0 for later
push dx ; save drive number
mov ax,MSG_SwitchDisks ; "Insert diskette for drive A:"
mov iHelpid,ax
cCall ListStdMsg,<ax> ; get message into bufStdMsg
pop ax ; restore AX = drive number
push ax ; save drive # again
lea bx,[bufStdMsg+26] ; BX = ptr to "A:"
add [bx],al ; change to 'B:' if necessary
mov ax,MB_OK ; display the message
push ax
mov ax,OFFSET DGROUP:bufStdMsg
push ax
call MsgBoxPsz
; actually switch the diskettes
pop dx ; DX = drive number
pop es ; ES = 0
mov es:[DOS_LOGICAL_DRIVE], dl ; Tell DOS we switched the
; diskettes
mov ah, 0dh ; reset the disk
int 21h
EndCheckSwitchDiskettes:
cEnd
page
;***
;
; FlushFile()
;
; Flushes all DOS buffers for the file to disk.
;
; Inputs: fd - file descriptor for the file to flush.
;
; Outputs:
;
; Uses: AX, DX.
;
;****
cProc FlushFile,<NEAR,PUBLIC>
parmW fd
cBegin
mov bx, [fd]
mov ah, 45H
int 21H ; Duplicate the handle
jc FlushFileExit
mov bx, ax
mov ah, 3eH
int 21H ; Close the dup'd handle to flush.
FlushFileExit:
cEnd
;***
;
; fstrcpy2( fpDst, fpSrc )
;
; Move null terminated string from Src to Dst
;
; Inputs:
; far pointer destination.
; far pointer source.
;
; Outputs: none.
;
; Uses: AX, CX.
;
;****
cProc fstrcpy2,<NEAR,PUBLIC>,<SI, DI, DS>
ParmD fpDst
ParmD fpSrc
cBegin
les di, fpDst
lds si, fpSrc
fstrcpy1:
lodsb
stosb
cmp al, 0
jnz fstrcpy1
cEnd
;***
;
; CbSzUi(psz)
;
; Added with revision [4] to save bytes.
;
; Return length of null-terminated string, not including the null
; The length is returned in bytes (not characters).
;
; Inputs:
; psz = near pointer to string
;
; Outputs: AX = length in bytes.
;
; Uses: Per convention
;
;****
cProc CbSzUI,<NEAR,PUBLIC>
cBegin
pop ax ; ax = return address
; parm(s) are on the stack
push cs ; push return segment
push ax ; push return offset
jmp CbSz ; "CALL" CbSz,<parm(s)>
cEnd <nogen>
;***
;
; fmemcpy(fpDst, fpSrc, cb )
;
; Move cb bytes (not characters) from Src to Dst
;
; Inputs:
; far pointer destination.
; far pointer source.
; unsigned integer for number of bytes to move.
;
; Outputs: none.
;
; Uses: AX, CX.
;
;****
cProc fmemcpy,<NEAR,PUBLIC>,<SI, DI, DS>
ParmD fpDst
ParmD fpSrc
ParmW cb
cBegin
mov cx, cb
jcxz fmemcpyEnd ;Early exit.
les di, fpDst
lds si, fpSrc
repz movsb
fmemcpyEnd:
cEnd
subttl Character mapping routines
page
; These tables now conform to IBM code page 850
labelB <Translation_Table>
DB 081h, 09ah, 'U'
DB 082h, 090h, 'E'
DB 083h, 0b6h, 'A'
DB 084h, 08eh, 'A'
DB 085h, 0b7h, 'A'
DB 086h, 08fh, 'A'
DB 087h, 080h, 'C'
DB 088h, 0d2h, 'E'
DB 089h, 0d3h, 'E'
DB 08ah, 0d4h, 'E'
DB 08bh, 0d8h, 'I'
DB 08ch, 0d7h, 'I'
DB 08dh, 0deh, 'I'
DB 091h, 092h, 'A'
DB 093h, 0e2h, 'O'
DB 094h, 099h, 'O'
DB 095h, 0e3h, 'O'
DB 096h, 0eah, 'U'
DB 097h, 0ebh, 'U'
DB 098h, 'Y', 'Y'
DB 09bh, 09dh, 'O'
DB 0a0h, 0b5h, 'A'
DB 0a1h, 0d6h, 'I'
DB 0a2h, 0e0h, 'O'
DB 0a3h, 0e9h, 'U'
DB 0a4h, 0a5h, 'N'
DB 0a6h, 'A', 'A'
DB 0a7h, 'O', 'O'
DB 0c6h, 0c7h, 'A'
DB 0e4h, 0e5h, 'O'
DB 0e7h, 0e8h, 'P'
DB 0ech, 0edh, 'Y'
DB 0, 0, 0 ; table end marker
;re-written in assembler, and moved here with revision [5].
;re-wrote table lookup with revision [7].
;***
;tolower, toupper, toupperNoAccent -- character conversion routines
;
;Purpose:
;
; Convert a character to either lower or upper case
; If char > 127, does an international mapping of the character
; If toupperNoAccent, converts it to the upper case version of the
; 'Normal' character.
;
;Entry:
; chr = character to convert
;
;Exit:
; AL = converted char
;
;Uses:
; Per convention
;
;*******************************************************************************
labelNP <PUBLIC, toupperNoAccent>
mov dx,UIOFFSET ReturnNoAccent ; return a upper case char
jmp short toupper2 ; without any accent
labelNP <PUBLIC, toupper>
mov dx,UIOFFSET ReturnUpper ; return a upper case char
toupper2:
mov cx,'Aa' ; CX = map lower to upper
jmp short MapChar
labelNP <PUBLIC, tolower>
mov dx,UIOFFSET ReturnLower ; return a lower case char
mov cx,'aA' ; CX = map upper to lower
cProc MapChar,<NEAR>
parmB chr ; char to convert
cBegin
; BX = translation table, CL = old A-Z start, CH = new A-Z start
mov al,chr ; AL = char to convert
or al,al ; above 127?
js DoTableLookup ; brif so -- map the sucker
push ax ; save char
sub al,cl ; make zero-relative
cmp al,26 ; out of range?
pop ax ; restore char
jae MapCharExit ; brif out of range - no change
sub al,cl ; make zero-relative again
add al,ch ; translate
jmp short MapCharExit ; done
DoTableLookup:
mov bx,UIOFFSET Translation_Table
TryNextEntry:
mov cx,cs:[bx] ; cl = lower case char
; ch = upper case char
jcxz MapCharExit ; brif end of table reached
inc bx ; prepare to do next one
inc bx
inc bx
cmp al,cl ; lower case char match?
je TableMatch ; brif so
cmp al,ch ; upper case char match?
jne TryNextEntry ; brif not -- try again
TableMatch:
jmp dx ; return right result
ReturnNoAccent:
mov al,cs:[bx-1] ; return no-accent character
SKIP2_PSW ; exit
ReturnUpper:
mov al,ch ; return upper case character
SKIP2_PSW ; exit
ReturnLower:
mov al,cl ; return lower case character
MapCharExit:
cEnd
;re-written in assembler, and moved here with revision [5].
;***
;lower -- convert a character string to lower case
;
;Purpose:
;
;Entry:
; psz = near pointer to string to convert
;
;Exit:
; string converted to lower case
;
;Uses:
; Per convention
;
;*******************************************************************************
cProc lower,<NEAR,PUBLIC>,<SI>
parmW psz ; string to convert
cBegin
mov si,psz ; si = * string to convert
NextChar:
lodsb ; al = next char in string
cCall tolower,<ax> ; convert the char
mov [si-1],al ; store converted char
or al,al ; all done?
jne NextChar ; brif not
cEnd
;***
;
; CbSizeMouseState
;
; Returns the number of bytes required to save the mouse state.
;
; Inputs: none
;
; Outputs: AX = number of bytes
;
; Uses: AX, BX, CX, DX.
;
;****
cProc cbSizeMouseState,<FAR,PUBLIC>
cBegin
xor ax,ax
cmp [fMousePresent], al
je @F
mov ax, 21
xor bx,bx ; Won't be changed if not supported
int 33H
mov ax, bx
@@:
cEnd
;***
;
; SaveMouseState
;
; Saves the mouse state in global memory
;
; Inputs: pointer to buffer for mouse save data
;
; Outputs: none
;
; Uses: AX, BX, CX, DX.
;
;****
cProc SaveMouseState,<FAR,PUBLIC>
parmD pBuffer
cBegin
les dx, [pBuffer]
mov ax, 22
int 33H
cEnd
;***
;
; RestoreMouseState
;
; Restores the mouse state saved by SaveMouse.
;
; Inputs: pBuffer - pointer to buffer containing saved mouse state.
;
; Outputs: none.
;
; Uses: AX, BX, CX, DX.
;
;****
cProc RestoreMouseState,<FAR,PUBLIC>
parmD pBuffer
cBegin
les dx, [pBuffer]
mov ax, 23
int 33H
cEnd
sEnd UI
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -