350 lines
8.3 KiB
NASM
350 lines
8.3 KiB
NASM
|
;++
|
||
|
;
|
||
|
; WOW v1.0
|
||
|
;
|
||
|
; Copyright (c) 1991, Microsoft Corporation
|
||
|
;
|
||
|
; WINSTR.ASM
|
||
|
; Win16 string services
|
||
|
;
|
||
|
; History:
|
||
|
;
|
||
|
; Created 18-Jun-1991 by Jeff Parsons (jeffpar)
|
||
|
; Copied from WIN31 and edited (as little as possible) for WOW16
|
||
|
;--
|
||
|
|
||
|
|
||
|
;****************************************************************************
|
||
|
;* *
|
||
|
;* WinStr.ASM - *
|
||
|
;* *
|
||
|
;* String related API calls to support different lanuages *
|
||
|
;* *
|
||
|
;****************************************************************************
|
||
|
|
||
|
TITLE WinStr.ASM
|
||
|
|
||
|
ifdef WOW
|
||
|
NOEXTERNS equ 1
|
||
|
endif
|
||
|
NOTEXT = 1
|
||
|
.xlist
|
||
|
include user.inc
|
||
|
.list
|
||
|
|
||
|
sBegin DATA
|
||
|
sEnd
|
||
|
|
||
|
createSeg _TEXT, CODE, WORD, PUBLIC, CODE
|
||
|
|
||
|
sBegin CODE
|
||
|
|
||
|
assumes CS,CODE
|
||
|
assumes DS,DATA
|
||
|
|
||
|
ExternNP Loc_IsConvertibleToUpperCase
|
||
|
ExternNP Loc_Upper
|
||
|
ExternFP IAnsiUpper
|
||
|
ExternFP IAnsiLower
|
||
|
ExternFP Ilstrcmpi
|
||
|
ifdef FE_SB
|
||
|
ExternFP IsDBCSLeadByte
|
||
|
endif
|
||
|
|
||
|
; Function codes for all the string functions in USER
|
||
|
;
|
||
|
ANSINEXT_ID equ 1
|
||
|
ANSIPREV_ID equ 2
|
||
|
ANSIUPPER_ID equ 3
|
||
|
ANSILOWER_ID equ 4
|
||
|
|
||
|
;--------------------------------------------------------------------------
|
||
|
; The order of entries in the following table can not be changed
|
||
|
; unless the *_ID codes are also changed in KERNEL also.
|
||
|
; ((FunctionCode - 1) << 1) is used as the index into this table
|
||
|
;
|
||
|
; Function Codes:
|
||
|
;
|
||
|
; NOTE: If you change the entries in this table, kindly update the
|
||
|
; *_ID statements above and also lString.asm of KERNEL.
|
||
|
;
|
||
|
;--------------------------------------------------------------------------
|
||
|
LabelW StringFuncTable
|
||
|
dw codeOFFSET IAnsiNext
|
||
|
dw codeOFFSET IAnsiPrev
|
||
|
dw codeOFFSET IAnsiUpper
|
||
|
dw codeOFFSET IAnsiLower
|
||
|
|
||
|
;*----------------------------------------------------------------------*
|
||
|
;* StringFunc() *
|
||
|
;* The string manipulation functions in kernel have been moved *
|
||
|
;* into USER. *
|
||
|
;* This is the common entry point in USER for all the string *
|
||
|
;* manipulation functions Kernel wants to call. Kernel jumps to *
|
||
|
;* this function with the function code in CX *
|
||
|
;* *
|
||
|
;* Input Parameters: *
|
||
|
;* [CX] contains the Function code. *
|
||
|
;* [sp] contains the FAR return address of the original caller of *
|
||
|
;* the string manipulation functions in Kernel *
|
||
|
;*----------------------------------------------------------------------*
|
||
|
|
||
|
cProc StringFunc, <FAR, PUBLIC>
|
||
|
cBegin nogen
|
||
|
xchg bx,cx ; move function code to BX
|
||
|
dec bx
|
||
|
shl bx, 1
|
||
|
jmp StringFuncTable[bx]
|
||
|
; Control does not comeback here. It returns directly
|
||
|
; to the caller
|
||
|
cEnd nogen
|
||
|
|
||
|
;*----------------------------------------------------------------------*
|
||
|
;* *
|
||
|
;* AnsiPrev() *
|
||
|
;* *
|
||
|
;*----------------------------------------------------------------------*
|
||
|
|
||
|
ifdef FE_SB
|
||
|
|
||
|
cProc IAnsiPrev,<PUBLIC,FAR>
|
||
|
; parmD pFirst ; [bx+10] es:di
|
||
|
; parmD pStr ; [bx+6] ds:si
|
||
|
|
||
|
cBegin nogen
|
||
|
push bp
|
||
|
mov bp,sp
|
||
|
|
||
|
push ds
|
||
|
push si
|
||
|
push di
|
||
|
|
||
|
lds si,[bp+6]
|
||
|
les di,[bp+10]
|
||
|
regptr dssi,ds,si
|
||
|
regptr esdi,es,di
|
||
|
cld
|
||
|
|
||
|
cmp si,di ; pointer to first char?
|
||
|
jz ap5 ; yes, just quit
|
||
|
|
||
|
dec si ; backup once
|
||
|
cmp si,di ; pointer to first char?
|
||
|
jz ap5 ; yse, just quit
|
||
|
|
||
|
ap1:
|
||
|
dec si ; backup once
|
||
|
mov al, [si] ; fetch a character
|
||
|
cCall IsDBCSLeadByte,<ax> ; DBCS lead byte candidate?
|
||
|
test ax,ax ;
|
||
|
jz ap2 ; jump if not.
|
||
|
cmp si,di ; backword exhausted?
|
||
|
jz ap3 ; jump if so
|
||
|
jmp ap1 ; repeat if not
|
||
|
ap2:
|
||
|
inc si ; adjust pointer correctly
|
||
|
ap3:
|
||
|
mov bx, [bp+6] ;
|
||
|
mov di, bx ; result in DI
|
||
|
dec di ;
|
||
|
sub bx, si ; how many characters backworded
|
||
|
test bx, 1 ; see even or odd...
|
||
|
jnz ap4 ; odd - previous char is SBCS
|
||
|
dec di ; make DI for DBCS
|
||
|
ap4:
|
||
|
mov si, di ; final result in SI
|
||
|
ap5:
|
||
|
mov ax,si
|
||
|
mov dx,ds
|
||
|
|
||
|
pop di
|
||
|
pop si
|
||
|
pop ds
|
||
|
|
||
|
pop bp
|
||
|
ret 8
|
||
|
cEnd nogen
|
||
|
|
||
|
else
|
||
|
|
||
|
cProc IAnsiPrev,<PUBLIC,FAR>
|
||
|
; parmD pFirst ; [bx+8] es:di
|
||
|
; parmD pStr ; [bx+4] ds:si
|
||
|
|
||
|
cBegin nogen
|
||
|
mov bx,sp
|
||
|
|
||
|
push ds
|
||
|
push si
|
||
|
push di
|
||
|
|
||
|
lds si,ss:[bx+4]
|
||
|
les di,ss:[bx+8]
|
||
|
regptr dssi,ds,si
|
||
|
regptr esdi,es,di
|
||
|
cld
|
||
|
|
||
|
cmp si,di ; pointer to first char?
|
||
|
jz ap3 ; yes, just quit
|
||
|
;;ifdef FE_SB
|
||
|
;; xchg si,di
|
||
|
;;ap1: mov dx,si
|
||
|
;; lodsb ; get a char
|
||
|
;; cCall IsDBCSLeadByte,<ax> ; is it kanji?
|
||
|
;; cmp al,0
|
||
|
;; je ap2 ; no, get next char
|
||
|
;; inc si ; yes, inc past second part
|
||
|
;;ap2: cmp si,di ; have we at or past end?
|
||
|
;; jb ap1 ; no, keep going
|
||
|
;; mov si,dx ; return previous pointer
|
||
|
;;else
|
||
|
dec si ; assume easy case...
|
||
|
;;endif ; FE_SB
|
||
|
ap3: mov ax,si
|
||
|
mov dx,ds
|
||
|
|
||
|
pop di
|
||
|
pop si
|
||
|
pop ds
|
||
|
ret 8
|
||
|
cEnd nogen
|
||
|
|
||
|
endif
|
||
|
|
||
|
;*----------------------------------------------------------------------*
|
||
|
;* *
|
||
|
;* AnsiNext() *
|
||
|
;* *
|
||
|
;*----------------------------------------------------------------------*
|
||
|
|
||
|
cProc IAnsiNext,<PUBLIC,FAR>
|
||
|
; parmD pStr
|
||
|
cBegin nogen
|
||
|
mov bx,sp
|
||
|
push di
|
||
|
les di,ss:[bx+4]
|
||
|
mov al,es:[di]
|
||
|
or al,al
|
||
|
jz an1
|
||
|
inc di
|
||
|
ifdef FE_SB
|
||
|
cCall IsDBCSLeadByte,<ax>
|
||
|
cmp al,0
|
||
|
je an1
|
||
|
inc di
|
||
|
endif ; FE_SB
|
||
|
an1: mov ax,di
|
||
|
mov dx,es
|
||
|
pop di
|
||
|
ret 4
|
||
|
cEnd nogen
|
||
|
|
||
|
;-----------------------------------------------------------------------
|
||
|
; MyAnsiUpper()
|
||
|
; convert string at es:di to upper case
|
||
|
;-----------------------------------------------------------------------
|
||
|
public MyAnsiUpper
|
||
|
MyAnsiUpper:
|
||
|
cld
|
||
|
mov si,di
|
||
|
mau1: lods byte ptr es:[si]
|
||
|
|
||
|
ifdef FE_SB
|
||
|
push ax
|
||
|
cCall IsDBCSLeadByte,<ax>
|
||
|
cmp ax,0
|
||
|
pop ax
|
||
|
je mau2
|
||
|
inc si
|
||
|
inc di
|
||
|
inc di
|
||
|
jmp short mau1
|
||
|
endif
|
||
|
|
||
|
mau2: call MyUpper
|
||
|
stosb
|
||
|
or al,al
|
||
|
jnz mau1
|
||
|
ret
|
||
|
|
||
|
;-----------------------------------------------------------------------
|
||
|
; MyAnsiLower()
|
||
|
; convert string at es:di to lower case
|
||
|
;-----------------------------------------------------------------------
|
||
|
public MyAnsiLower
|
||
|
MyAnsiLower:
|
||
|
cld
|
||
|
mov si,di
|
||
|
mal1: lods byte ptr es:[si]
|
||
|
|
||
|
ifdef FE_SB
|
||
|
push ax
|
||
|
cCall IsDBCSLeadByte,<ax> ; first byte of double byte?
|
||
|
cmp ax,0
|
||
|
pop ax
|
||
|
je mal2 ; no just do normal stuff
|
||
|
inc si ; skip the two bytes
|
||
|
inc di
|
||
|
inc di
|
||
|
jmp short mal1
|
||
|
endif
|
||
|
|
||
|
mal2: call MyLower
|
||
|
stosb
|
||
|
or al,al
|
||
|
jnz mal1
|
||
|
ret
|
||
|
|
||
|
;-------------------------------------------------------------------------
|
||
|
; MyUpper()
|
||
|
; convert lower case to upper, must preserve es,di,cx
|
||
|
;-------------------------------------------------------------------------
|
||
|
public MyUpper
|
||
|
MyUpper:
|
||
|
call Loc_IsConvertibleToUpperCase ; Check if it is a lower case char
|
||
|
; that has an uppercase equivalent
|
||
|
jnc myu1 ;
|
||
|
sub al,'a'-'A'
|
||
|
myu1: ret
|
||
|
|
||
|
ifdef KANJI
|
||
|
#################### KANJI ###############################################
|
||
|
; convert upper case to lower, must preserve es,di,cx
|
||
|
public MyLower
|
||
|
MyLower:
|
||
|
cmp al,'A'
|
||
|
jb myl2
|
||
|
cmp al,'Z'
|
||
|
jbe myl1
|
||
|
|
||
|
push ds
|
||
|
SetKernelDS
|
||
|
cmp [fFarEast],1 ; this is a far east kbd 1/12/87 linsh
|
||
|
pop ds
|
||
|
UnSetKernelDS
|
||
|
jge myl2 ; yes do nothing to the 0C0H - 0DEH range
|
||
|
|
||
|
cmp al,0C0H ; this is lower case a with a back slash
|
||
|
jb myl2
|
||
|
cmp al,0DEH
|
||
|
ja myl2
|
||
|
myl1: add al,'a'-'A'
|
||
|
myl2: ret
|
||
|
#################### KANJI ###############################################
|
||
|
endif
|
||
|
|
||
|
;--------------------------------------------------------------------------
|
||
|
; MyLower()
|
||
|
; convert upper case to lower, must preserve es,di,cx
|
||
|
;--------------------------------------------------------------------------
|
||
|
public MyLower
|
||
|
MyLower:
|
||
|
call Loc_Upper
|
||
|
jnc myl1
|
||
|
add al, 'a'-'A'
|
||
|
myl1:
|
||
|
ret
|
||
|
|
||
|
sEnd CODE
|
||
|
end
|