;++ ; ; 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 endif .xlist include user.inc .list ;*==========================================================================* ;* * ;* FFFE Segment Definition - * ;* * ;*==========================================================================* createSeg _%SEGNAME, %SEGNAME, WORD, PUBLIC, CODE assumes cs,%SEGNAME assumes ds,DATA ExternFP ExternFP ExternFP 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, ;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, ;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, ;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, ;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, ;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, , 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, ;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, , 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,, 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, , 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, ; 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, , 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, , 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