|
|
;++ ; ; WOW v1.0 ; ; Copyright (c) 1991, Microsoft Corporation ; ; WINUTIL.ASM ; Win16 general utility routines ; ; History: ; ; Created 28-May-1991 by Jeff Parsons (jeffpar) ; Copied from WIN31 and edited (as little as possible) for WOW16. ; At this time, all we want is MultDiv() and LCopyStruct(), which the ; edit controls use. ;--
;**************************************************************************** ;* * ;* WINUTIL.ASM - * ;* * ;* General Utility Routines * ;* * ;****************************************************************************
title WINUTIL.ASM - General Utility routines
ifdef WOW NOEXTERNS equ 1 SEGNAME equ <TEXT> endif .xlist include user.inc .list
;*==========================================================================* ;* * ;* FFFE Segment Definition - * ;* * ;*==========================================================================*
createSeg _%SEGNAME, %SEGNAME, WORD, PUBLIC, CODE
assumes cs,%SEGNAME assumes ds,DATA
ExternFP <GetStockObject> ExternFP <GetTextExtent> ExternFP <TextOut>
ExternA <__WinFlags>
ifdef FE_SB ; **** April,26,1990 by KenjiK **** ExternFP IsDBCSLeadByte endif
sBegin DATA sEnd DATA
sBegin %SEGNAME
;*--------------------------------------------------------------------------* ;* * ;* MultDiv() - * ;* * ;*--------------------------------------------------------------------------*
; Calc a * b / c, with 32-bit intermediate result
cProc MultDiv, <PUBLIC, FAR>
;ParmW a ;ParmW b ;ParmW c
cBegin nogen mov bx,sp ; calc (a * b + c/2) / c mov ax,ss:[bx+8] ; ax = a mov cx,ss:[bx+4] ; cx = c or cx,cx jz mdexit ; just return A if we'll get divide by 0 mov dx,ss:[bx+6] ; dx=b imul dx
mov bx,cx ; save a copy of c in bx for later shr cx,1 ; add in cx/2 for rounding add ax,cx adc dx,0 ; add in carry if needed ; get c from bx register since idev mem idiv bx ; doesn't work on tandy 2000's mdexit: retf 6 cEnd nogen
ifdef DISABLE
;*--------------------------------------------------------------------------* ;* * ;* min() - * ;* * ;*--------------------------------------------------------------------------*
cProc min, <FAR, PUBLIC>
;ParmW a ;ParmW b
cBegin nogen mov bx,sp mov ax,ss:[bx+6] ;ax = a mov cx,ss:[bx+4] ;cx = b cmp ax,cx jl min10 mov ax,cx min10: retf 4 cEnd nogen
;*--------------------------------------------------------------------------* ;* * ;* max() - * ;* * ;*--------------------------------------------------------------------------*
cProc max, <FAR, PUBLIC>
;ParmW a ;ParmW b
cBegin nogen mov bx,sp mov ax,ss:[bx+6] ;ax = a mov cx,ss:[bx+4] ;cx = b cmp ax,cx jg max10 mov ax,cx max10: retf 4 cEnd nogen
;*--------------------------------------------------------------------------* ;* * ;* umin() - * ;* * ;*--------------------------------------------------------------------------*
cProc umin, <FAR, PUBLIC>
;ParmW a ;ParmW b
cBegin nogen mov bx,sp mov ax,ss:[bx+6] ;ax = a mov cx,ss:[bx+4] ;cx = b cmp ax,cx jb umin10 mov ax,cx umin10: retf 4 cEnd nogen
;*--------------------------------------------------------------------------* ;* * ;* umax() - * ;* * ;*--------------------------------------------------------------------------*
cProc umax, <FAR, PUBLIC>
;ParmW a ;ParmW b
cBegin nogen mov bx,sp mov ax,ss:[bx+6] ;ax = a mov cx,ss:[bx+4] ;cx = b cmp ax,cx ja umax10 mov ax,cx umax10: retf 4 cEnd nogen
endif ; DISABLE
;*--------------------------------------------------------------------------* ;* * ;* LFillStruct() - * ;* * ;*--------------------------------------------------------------------------*
cProc LFillStruct, <PUBLIC, FAR, NODATA, ATOMIC>, <di>
parmD lpStruct parmW cb parmW fillChar
cBegin les di,lpStruct mov cx,cb mov ax,fillChar cld rep stosb
cEnd LFillStruct
;*--------------------------------------------------------------------------* ;* * ;* LCopyStruct() - * ;* * ;*--------------------------------------------------------------------------*
; LCopyStruct(pbSrc, pbDst, cb)
cProc LCopyStruct, <FAR, PUBLIC> ;ParmD pSrc ;ParmD pDest ;ParmW cb cBegin nogen mov bx,sp
mov cx,ss:[bx+4] ; cx = cb jcxz lcopynone ; Nothing to do if count == 0
push si push di mov dx,ds ; save ds
lds si,ss:[bx+4+2+4] ; ds:si = pSrc les di,ss:[bx+4+2] ; es:di = pDst
cmp si,di ; Could they overlap? jae lcopyok
mov ax,cx ; Yes: copy from the top down dec ax dec ax add si,ax add di,ax
std shr cx,1 rep movsw jnc @F ; an odd byte to blt? inc si ; went one too far: back up. inc di movsb @@: cld jmps lcopydone
lcopyok: cld shr cx,1 rep movsw jnc @F ; an odd byte to blt? movsb @@:
lcopydone: mov ds,dx pop di pop si lcopynone: retf 4+4+2 cEnd nogen
ifndef WOW ;*--------------------------------------------------------------------------* ;* * ;* The following routines are "Movable DS" equivalents of their normal * ;* counterparts. The PS stands for "Pointer Safe." They prevent problems * ;* which occur when an app passes in a pointer to an object in its DS * ;* which we somehow cause to move. To prevent this problem, we copy what * ;* the pointer points to into USER's DS and use a pointer to our copy * ;* instead. * ;* * ;*--------------------------------------------------------------------------*
;*--------------------------------------------------------------------------* ;* * ;* PSGetTextExtent() - * ;* * ;*--------------------------------------------------------------------------*
ifndef PMODE
cProc PSGetTextExtent, <PUBLIC, FAR, NODATA>, <si,di>
ParmW hdc ParmD lpch ParmW cch
LocalV rgch, 128 ; max 128 chars
cBegin mov ax,__WinFlags test al,WF_PMODE errnz high(WF_PMODE) jz PSGTE_RealMode
push hdc pushd lpch push cch jmp short PSGTE_GetExtent
PSGTE_RealMode: lea di,rgch ; es:di = dest push ss pop es lds si,lpch ; ds:si = src mov cx,cch ; count = min(cch, 128) mov ax,128 cmp cx,ax jbe gte100 xchg ax,cx
gte100: push hdc ; Push args before rep movsb destroys push ss ; cx and di push di push cx
cld rep movsb ; Copy string to local storage
PSGTE_GetExtent: call GetTextExtent
cEnd PSGetTextExtent
;*--------------------------------------------------------------------------* ;* * ;* PSTextOut() - * ;* * ;*--------------------------------------------------------------------------*
; void PSTextOut(hdc, lpch, cch)
cProc PSTextOut,<PUBLIC, FAR, NODATA>, <si, di>
ParmW hdc ParmW x ParmW y ParmD lpch ParmW cch
LocalV rgch, 255 ; max 255 chars
cBegin mov ax,__WinFlags test al,WF_PMODE errnz high(WF_PMODE) jz PSTO_RealMode
push hdc push x push y pushd lpch push cch jmp short PSTO_TextOut
PSTO_RealMode: lea di,rgch ; es:di = dest push ss pop es lds si,lpch ; ds:si = src mov cx,cch ; count = min(cch, 255) mov ax,255 cmp cx,ax jbe to100 xchg ax,cx
to100: push hdc ; Push args before rep movsb destroys push x ; cx and di push y push ss ; Push &rgch[0] push di push cx
cld rep movsb ; copy string before we go
PSTO_TextOut: call TextOut
cEnd PSTextOut
endif ; ifndef PMODE
;*--------------------------------------------------------------------------* ;* * ;* FindCharPosition() - * ;* * ;*--------------------------------------------------------------------------*
; Finds position of char ch in string psz. If none, returns the length of ; the string.
cProc FindCharPosition, <FAR, PUBLIC, NODATA>, <si, ds>
ParmD psz ParmB char
cBegin lds si,psz fcp100: lodsb ; get a byte or al,al jz fcp200 ifdef FE_SB ; **** April,26,1990 by KenjiK **** sub ah,ah push ax cCall IsDBCSLeadByte,<ax> ; first byte of double byte? test ax,ax pop ax jz fcp150 ; no just do normal stuff lodsb ; skip second byte of double byte jmps fcp100 ; and do again fcp150: endif cmp al,char jnz fcp100 fcp200: xchg ax,si ; calc char index: pch - 1 - psz dec ax sub ax,off_psz
cEnd FindCharPosition
endif ;WOW
sEnd %SEGNAME
ifndef WOW ;*==========================================================================* ;* * ;* RUNAPP Segment Definition - * ;* * ;*==========================================================================*
createSeg _RUNAPP, RUNAPP, BYTE, PUBLIC, CODE
sBegin RUNAPP
assumes cs,RUNAPP assumes ds,DATA
;*--------------------------------------------------------------------------* ;* * ;* CrunchX2() - * ;* * ;*--------------------------------------------------------------------------*
; This routine copies the pile of bits from the source pointer ; to the dest pointer doing the integer crunch as it goes ; it will favor black (0) to white (1) and will keep the destinations ; widthbytes even. ; ; Assumptions: Neither source nor destination are greater than 64K ; Either the two bitmaps, lpSrc and lpDst are disjoint ; or lpDst <= lpSrc (i.e. we fill from the front) ; WidthBytes is even
cProc CrunchX2, <FAR, PUBLIC, NODATA>, <ds, si, di>
parmD lpSrc parmD lpDst parmW WidthBytes parmW Height
LocalW dwb ; destination width if not corrected LocalW destinc ; used to force dest width even each scan
cBegin cld lds si,lpSrc les di,lpDst mov bx,Height
; Compute destination widthbytes mov ax,WidthBytes ; must be even shr ax,1 ; widthbytes for the destination mov dwb,ax and ax,1 ; iff odd must inc dest pointer mov destinc,ax ; at the end of each scan sub di,ax
NextSX: dec bx jl exitX mov cx,dwb add di,destinc
CrunchBX: lodsw mov dx,ax rol ax,1 and dx,ax ; this and selects 0 in favor of 1 mov al,dl shl ax,1 shl al,1 shl ax,1 shl al,1 shl ax,1 shl al,1 shl ax,1 mov al,dh shl ax,1 shl al,1 shl ax,1 shl al,1 shl ax,1 shl al,1 shl ax,1 mov al,ah stosb loop CrunchBX jmp NextSX exitX:
cEnd CrunchX2
;*--------------------------------------------------------------------------* ;* * ;* CrunchY() - * ;* * ;*--------------------------------------------------------------------------*
cProc CrunchY, <FAR, PUBLIC, NODATA>, <ds, si, di>
parmD lpSrc parmD lpDst parmW WidthBytes parmW Height parmW scale
LocalW groupcount ;Height/scale LocalW groupinc ;WidthBytes * Height/Scale LocalW scancount ;counter of bytes in scan reset each group LocalW bytecount ;number of bytes joined = scale - 1
cBegin cld lds si,lpSrc les di,lpDst
; Compute group count mov bx,scale ; only scale positive cmp bx,1 jle CopyBitmap mov ax,Height xor dx,dx div bx mov groupcount,ax ; Height/scale mov cx,WidthBytes ; must be even dec bx mov bytecount,bx mov ax,bx mul cx mov groupinc,ax ; WidthBytes * (scale - 1) mov dx,cx mov bx,si sub bx,groupinc dec bx dec bx
NextGroup: dec groupcount jl exitY add bx,groupinc mov ax,dx shr ax,1 mov scancount,ax
NextByte: dec scancount jl NextGroup inc bx inc bx mov si,bx mov ax,[si] mov cx,bytecount
CrunchBY: add si,dx and ax,[si] loop CrunchBY stosw jmp NextByte
CopyBitmap: mov ax,Height mul WidthBytes shr ax,1 mov cx,ax rep movsw
exitY: cEnd CrunchY
sEnd RUNAPP
endif ;WOW
end
|