TITLE - Converted Winrect.c to Assembler .286p .xlist include wow.inc include wowusr.inc include cmacros.inc NOEXTERNS=1 ; to suppress including most of the stuff in user.inc include user.inc .list sBegin CODE assumes cs, CODE assumes ds, DATA ;****************************************************************************** ; ORIGINAL C SOURCE ; ;*void FAR SetRect(pRect,left,top,right,bottom) ;*LPRECT pRect; ;*int top,left,bottom,right; ;*{ ;* pRect->top = top; ;* pRect->left = left; ;* pRect->bottom = bottom; ;* pRect->right = right; ;*} ;****************************************************************************** cProcVDO SetRect, ;ParmD lprc ;ParmW left ;ParmW top ;ParmW right ;ParmW bottom cBegin nogen mov bx,sp mov cx,di beg_fault_trap sr_trap cld les di,ss:[bx]+4+2+2+2+2 mov ax,ss:[bx]+4+2+2+2 stosw mov ax,ss:[bx]+4+2+2 stosw mov ax,ss:[bx]+4+2 stosw mov ax,ss:[bx]+4 stosw end_fault_trap sr_cont: mov di,cx retf 4+2+2+2+2 cEnd nogen sr_trap: fault_fix_stack jmp short sr_cont ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*int FAR SetRectEmpty(pRect) ;*LPRECT pRect; ;*{ ;* LFillStruct(pRect,sizeof(RECT),0); ;*} ;* ;****************************************************************************** LabelVDO SetRectEmpty pop ax pop dx pop bx pop cx push dx push ax xchg di,bx beg_fault_trap sre_trap mov es,cx xor ax,ax cld stosw stosw stosw stosw end_fault_trap sre_cont: mov di,bx retf sre_trap: fault_fix_stack jmp short sre_cont ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*int FAR CopyRect(pDstRect,pSrcRect) ;*LPRECT pSrcRect; /*ptr to source rect */ ;*LPRECT pDstRect; /*Ptr to dest rect */ ;*{ ;* LCopyStruct(pSrcRect,pDstRect,sizeof(RECT)); ;* /*copy from source to dest */ ;*} ;* ;****************************************************************************** cProcVDO CopyRect, , parmD lpDstRect ;long pointer to DstRect parmD lpSrcRect ;long pointer to SrcRect cBegin beg_fault_trap cr_trap lds si, lpSrcRect ;mov into ds:si a far pointer to SrcRect les di, lpDstRect ;mov into es:di far pointer to DstRect cld ;clear direction flag for increment stuff movsw movsw movsw movsw end_fault_trap cr_cont: cEnd cr_trap: fault_fix_stack jmp short cr_cont ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*BOOL FAR IsRectEmpty(pRect) ;*LPRECT pRect; ;*{ ;* return(((pRect->right-pRect->left<=0)||(pRect->bottom-pRect->top<=0)) ? TRUE : FALSE); ;*} ;* ;****************************************************************************** LabelVDO IsRectEmpty pop ax pop dx pop bx ; get lprc pop cx push dx push ax beg_fault_trap ire_trap mov es,cx mov ax,TRUE mov cx,es:[bx].rcRight cmp cx,es:[bx].rcLeft jle empty0 mov cx,es:[bx].rcBottom cmp cx,es:[bx].rcTop jle empty0 xor ax,ax end_fault_trap empty0: retf ire_trap: fault_fix_stack jmp short empty0 ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*BOOL FAR PtInRect(lprc, pt) ;*LPRECT lprc; ;*POINT pt; ;*{ ;* return(pt.x >= lprc->left && pt.x < lprc->right && ;* pt.y >= lprc->top && pt.y < lprc->bottom); ;*} ;* ;****************************************************************************** cProcVDO PtInRect,, ; parmD lpRect ; parmD lpPoint cBegin nogen mov bx,sp push ds push si mov cx,ss:[bx+4] ; cx = pt.x mov dx,ss:[bx+6] ; dx = pt.y beg_fault_trap pir_trap lds si,ss:[bx+8] ; lpRect cld xor bx,bx ; Result = FALSE lodsw ; AX = lpRect->left cmp cx,ax ; xcoord < left? jl PtNotInRect ; Yes, not in rectangle lodsw ; AX = lpRect->top cmp dx,ax ; ycoord < top? jl PtNotInRect ; Yes, not in rectangle lodsw ; AX = lpRect->right cmp cx,ax ; xcoord >= right? jge PtNotInRect ; Yes, not in rectangle lodsw ; AX = lpRect->bottom cmp dx,ax ; ycoord >= bottom? jge PtNotInRect ; Yes, not in rectangle inc bx ; Point in rectangle, result = TRUE end_fault_trap PtNotInRect: mov ax,bx pop si pop ds retf 8 cEnd nogen pir_trap: fault_fix_stack jmp short PtNotInRect ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*int FAR OffsetRect(pRect, x, y) ;*LPRECT pRect; ;*int x; ;*int y; ;*{ ;* pRect->left += x; ;* pRect->right += x; ;* pRect->top += y; ;* pRect->bottom += y; ;*} ;* ;****************************************************************************** cProcVDO OffsetRect,, ; parmD lpRect ;far pointer to struct type rect ; parmW xDelta ;X delta ; parmW yDelta ;Y Delta cBegin nogen mov bx,sp push ds beg_fault_trap or_trap mov dx,ss:[bx+6] ; dx = dx mov cx,ss:[bx+4] ; CX = dy lds bx,ss:[bx+8] ; ds:bx = lprc add [bx].rcLeft,dx add [bx].rcTop,cx add [bx].rcRight,dx add [bx].rcBottom,cx end_fault_trap or_cont: pop ds retf 8 cEnd or_trap: fault_fix_stack jmp short or_cont ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*int FAR InflateRect(pRect, x, y) ;*LPRECT pRect; ;*int x; ;*int y; ;*{ ;* pRect->left -= x; ;* pRect->right += x; ;* pRect->top -= y; ;* pRect->bottom += y; ;*} ;* ;****************************************************************************** cProcVDO InflateRect,, ; parmD lpRect ;far pointer to struct type rect ; parmW xOffset ; parmW yOffset cBegin nogen mov bx,sp push ds beg_fault_trap ir_trap mov dx,ss:[bx+6] ; dx = dx mov cx,ss:[bx+4] ; CX = dy lds bx,ss:[bx+8] ; ds:bx = lprc sub [bx].rcLeft,dx sub [bx].rcTop,cx add [bx].rcRight,dx add [bx].rcBottom,cx end_fault_trap ir_cont: pop ds retf 8 cEnd ir_trap: fault_fix_stack jmp short ir_cont ;----------------------------------------------------------------- ; ; IntersectRect(lprcDst, lprcSrc1, lprcSrc2); ; cProcVDO IntersectRect,, ParmD lprcDst ParmD lprcSrc1 ParmD lprcSrc2 cBegin beg_fault_trap irc_trap lds si,lprcSrc1 ; point at source rects les di,lprcSrc2 mov ax,[si].rcLeft ; new left = cx = max(rc1.left, rc2.left) mov cx,es:[di].rcLeft cmp ax,cx jl ir100 xchg ax,cx ir100: mov ax,[si].rcRight ; new right = dx = min(rc1.right, rc2.right) mov dx,es:[di].rcRight cmp ax,dx jg ir200 xchg ax,dx ir200: cmp cx,dx ; is left >= right? jge irempty ; yes - return empty rect mov ax,[si].rcTop ; new top = cx = max(rc1.top, rc2.top) mov bx,es:[di].rcTop cmp ax,bx jl ir300 xchg ax,bx ir300: mov ax,[si].rcBottom ; new bottom = dx = min(rc1.bottom, rc2.bottom) mov di,es:[di].rcBottom cmp ax,di jg ir400 xchg ax,di ir400: cmp bx,di ; is top >= bottom? jge irempty ; no: store result lds si,lprcDst ; store away new right & left mov [si].rcLeft,cx mov [si].rcTop,bx mov [si].rcRight,dx mov [si].rcBottom,di mov al,TRUE ; return TRUE end_fault_trap irexit: cEnd irc_trap: fault_fix_stack irempty: les di,lprcDst ; point at dst rect xor ax,ax ; set to (0, 0, 0, 0) cld stosw stosw stosw stosw ; return FALSE jmps irexit ;============================================================================= ; ; BOOL UnionRect(lprcDest, lprcSrc1, lprcSrc2) ; LPRECT lprcDest; ; LPRECT lprcSrc1; ; LPRECT lprcSrc2; ; ; Calculates *lprcDest as the minimum rectangle that bounds both ; *lprcSrc1 and *lprcSrc2. If either rectangle is empty, lprcDest ; is set to the other rectangle. Returns TRUE if the result is a non-empty ; rectangle, FALSE otherwise. ; ; cProcVDO UnionRect,, ParmD lprcDest ParmD lprcSrc1 ParmD lprcSrc2 LocalW wTemp cBegin beg_fault_trap ur_trap lds si,lprcSrc1 les di,lprcSrc2 push es push di wcall IIsRectEmpty push ax ; save result ; IsRectEmpty trashes es.... push es push ds push si wcall IIsRectEmpty pop es ; restore it pop cx ;ax = IsRectEmpty(1), cx = IsRectEmpty(2) or ax,ax jnz URrc1empty mov ax,TRUE ; return true, not both empty or cx,cx jz URnormalcase jmps URrc2empty URrc1empty: lds si,lprcSrc2 jcxz URrc2empty ; rc2 not empty, ax has true for return xor ax,ax ; return false, both empty URrc2empty: les di,lprcDest cld movsw movsw movsw movsw jmps URexit ; src1 and src2 not empty URnormalcase: mov ax,[si].rcLeft ; bx = min(Src1.left, Src2.left) mov cx,es:[di].rcLeft cmp ax,cx jl URleft xchg ax,cx URleft: mov bx,ax mov ax,[si].rcTop ; dx = min(Src1.top, Src2.top) mov cx,es:[di].rcTop cmp ax,cx jl URtop xchg ax,cx URtop: mov dx,ax mov ax,[si].rcRight ; wTemp = max(Src1.right, Src2.right) mov cx,es:[di].rcRight cmp ax,cx jg URright xchg ax,cx URright: mov wTemp,ax mov ax,[si].rcBottom ; ax = max(Src1.bottom, Src2.bottom) mov cx,es:[di].rcBottom cmp ax,cx jg URbottom xchg ax,cx URbottom: les di,lprcDest ; fill into lprcDest mov es:[di].rcLeft,bx mov es:[di].rcTop,dx mov es:[di].rcBottom,ax mov ax,wTemp mov es:[di].rcRight,ax end_fault_trap ur_true: mov ax,TRUE ; return true, not both empty URexit: cEnd ur_trap: fault_fix_stack jmp ur_true ;****************************************************************************** ;* ORIGINAL C SOURCE ;* ;*BOOL FAR EqualRect(lpRect1, lpRect2) ;*LPRECT lpRect1; ;*LPRECT lpRect2; ;*{ ;* return lpRect1->left == lpRect2->left && lpRect1->top == lpRect2->top ;* && lpRect1->right == lpRect1->right && lpRect1->bottom == ;* lpRect2->bottom; ;*} ;* ;****************************************************************************** cProcVDO EqualRect, , parmD lpRect1 parmD lpRect2 cBegin xor ax,ax ; assume FALSE beg_fault_trap er_trap lds si,lpRect1 les di,lpRect2 mov cx,4 cld repz cmpsw jnz er10 inc al end_fault_trap er10: cEnd er_trap: fault_fix_stack jmp er10 ;**************************************************************************** ; The following Routine to subtract one rectangle from another is lifted ; from PM and Modified by Sankar. ; ;**************************************************************************** ;** Public Routine ****************************************************-; ; BOOL far SubtractRect(lprcDest, lprc1, lprc2) ; LPRECT lprcDest; ; LPRECT lprcSrc1; ; LPRECT lprcSrc2; ; ; This function subtracts *lprc2 from *lprc1, returning the result ; in *lprcDest. Returns TRUE if *lprcDest is non-empty, FALSE otherwise. ; ; Warning: Subtracting one rectangle from another may not ; always result in a rectangular area; in this case ; WinSubtractRect will return *lprc1 in *lprcDest. ; For this reason, WinSubtractRect provides only an ; approximation of subtraction. However, the area ; described by *lprcDest will always be greater ; than or equal to the "true" result of the ; subtraction. ; ; History : ; Added by Sankar on July 27, 1988 ;**********************************************************************-; cProcVDO SubtractRect, , ParmD lprcDest ParmD lprc1 ParmD lprc2 LocalV rc,%size RECT cBegin ; ; First copy lprc1 into lprcDest. ; beg_fault_trap sbr_trap lds si,lprc1 les di,lprcDest cld movsw movsw movsw movsw lds si,lprcDest ; ds:[si] = lprcDest. lea di,rc ; ss:[di] = &rc ; ; We're subtracting lprc2 from lprc1. Make sure they at least ; intersect each other. If not, return TRUE. ; push ss ; pushd &rc push di push ds ; pushd lprcDest push si push seg_lprc2 ; pushd lprc2 push off_lprc2 wcall IIntersectRect or ax,ax ; Did we intersect? jz sr700 ; If no, skip to check empty rect ; ; Now make sure that we can subtract lprc2 from lprc1 and get a rect. ; errnz errnz errnz errnz ; ; We make a loop that iterates twice - once for the x's and once for the ; y's. We want at least 3 sides of lprc2 to be outside of 3 sides of lprc1. ; xor cx,cx xor dx,dx dec cx ; ; ds:si points to lprc1 (actually lprcDest) ; ss:di points to rc on stack ; sr100: inc cx mov bx,cx shl bx,1 ; bx is a Word pointer mov ax,ss:[di+bx].rcLeft ; if lprc2 left/top is > lprc1 l/t, cmp ax,ds:[si+bx].rcLeft jg sr200 ; then inside the rect. inc dx sr200: mov ax,ss:[di+bx].rcRight ; if lprc2 right/bottom is > lprc1 r/b, cmp ax,ds:[si+bx].rcRight jl sr300 ; then inside the rect. inc dx sr300: jcxz sr100 ; loop one more time... cmp dx,3 ; Are 3 sides outside? If not, jb sr700 ; skip to check empty rect code cmp dx,4 ; Is rc1 completely inside rc2? If so, jne sr350 ; empty lprcDest and return TRUE pushd lprcDest ; empty that puppy wcall ISetRectEmpty xor ax,ax ; Go return FALSE. jmps srExit sr350: ; ; Now we know that we can take lprc2 from lprc1 and leave a rect, so ; now we perform the 'subtract rect'. Interate twice, again once for the ; x's and once for the y's. ; xor cx,cx dec cx sr400: inc cx mov bx,cx shl bx,1 ; Make bx a Word pointer mov dx,ss:[di+bx].rcLeft ; New right/Bottom border? cmp dx,ds:[si+bx].rcLeft jle sr500 mov ds:[si+bx].rcRight,dx jmps sr600 sr500: mov dx,ss:[di+bx].rcRight ; New left/top border? cmp dx,ds:[si+bx].rcRight jge sr600 mov ds:[si+bx].rcLeft,dx sr600: jcxz sr400 sr700: xor ax,ax ; Assume it is empty: FALSE mov cx,ds:[si].rcRight cmp cx,ds:[si].rcLeft jle SrExit mov cx,ds:[si].rcBottom cmp cx,ds:[si].rcTop jle SrExit inc al ; Non-empty: return TRUE. end_fault_trap srExit: cEnd sbr_trap: fault_fix_stack xor ax,ax ; return FALSE jmp srExit ;**************************************************************************** ; ; void FAR SplitRectangle(lprcRect, lprcRectArray, wcx, wcy) ; LPRECT lprcRect ; RECT lprcRectArray[4] ; ; This splits the given rectangular frame into four segments and stores ; them in the given array ; ; Pseudo code: ; ----------- ; ; cxWidth = lprcRect -> rcRight - lprcRect -> rcLeft - wcx; ; cyWidth = lprcRect -> rcBottom - lprcRect -> rcTop - wcy; ; ; A = -cyWidth; ; B = -cxWidth; ; ; for (i = 0; i < 4; i++) ; { ; lprcRectArray[i][i] = lprcRect[i]; ; lprcRectArray[i][(i+1)&3] = lprcRect[(i+3)&3] + A; ; lprcRectArray[i][(i+2)&3] = lprcRect[(i+2)&3] + B; ; lprcRectArray[i][(i+3)&3] = lprcRect[(i+3)]; ; ; TMP = A; ; A = -B; ; B = TMP; ; } ; ; Note: ; Value of i Value of A Value of B ; ---------- ---------- ---------- ; 0 -cyWidth -cxWidth ; 1 +cxWidth -cyWidth ; 2 +cyWidth +cxWidth ; 3 -cxWidth +cyWidth ; ; ;*************************************************************************** cProc SplitRectangle, , ParmD ; Rect and Array Parmw ; Border widths cBegin les di, lprcRectArray ; es:di => lprcRectArray lds si, lprcRect ; ds:si => given rectangle ; Calculate the value of -cxWidth mov ax, [si].rcLeft sub ax, [si].rcRight add ax, wcx push ax ; Save B on stack. ; Calculate the value of -cyWidth mov ax, [si].rcTop sub ax, [si].rcBottom add ax, wcy push ax ; Save A on stack ; Initialise the loop related variables xor cx, cx ; Loop count xor bx, bx ; Index into Rect Structure. LoopSt: ; lprcRectArray[i][i] = lprcRect[i]; mov ax, [si+bx] mov es:[di+bx], ax ; lprcRectArray[i][(i+1)&3] = lprcRect[(i+3)&3] + A; inc bx inc bx ; Make it a word pointer and bx, 6 push bx ; Save (i+1) tempoarily add bx, 4 ; Calculate (i+3) and bx, 6 mov ax, [si+bx] ; lprcRect[(i+3)] is taken pop bx ; (i+1) is returned to bx pop dx ; Value "A" is taken from stack add ax, dx mov es:[di+bx], ax ; Swap A and B on stack. A is in DX pop ax ; Value B from Stack. push dx ; B = A; Push ax ; A = B; ; Now B is on top of stack and A is below it. ; lprcRectArray[i][(i+2)&3] = lprcRect[(i+2)&3] + B; inc bx inc bx ; (i+2) is calculated and bx, 6 mov ax, [si+bx] pop dx ; pop B add ax, dx mov es:[di+bx], ax neg dx ; make -B push dx ; lprcRectArray[i][(i+3)&3] = lprcRect[(i+3)]; inc bx inc bx and bx, 6 ; make [(i+3)&3] mov ax, [si+bx] mov es:[di+bx], ax inc cx cmp cx, 4 jge exit mov bx, cx shl bx, 1 ; Make it a word pointer add di, size RECT ; Make it point to next rect in the array jmp LoopSt exit: ; A and B exist on stack. So,Pop them add sp, 4 cEnd sEnd TEXT end