;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CURSOR2.ASM
;*
;* DESCRIPTIVE NAME = Cursor functions.
;*
;*
;* VERSION      V2.0
;*
;* DATE         10/19/91
;*
;* DESCRIPTION  Cursor functions.                                                              
;*                                                                            
;* FUNCTIONS    DeviceSetCursor
;*              SetColorCursor 
;*              SetDeviceCursor
;*              far_exclude
;*              far_unexclude 
;*              SetScreenBusy 
;*              CursorInit 
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*****************************************************************************/

        PAGE     60,132
        TITLE    Cursor Functions
        SUBTITLE Header
.386
        
.MODEL FLAT,SYSCALL

INCL_DDIMISC       EQU 1
INCL_GPIERRORS     EQU 1
INCL_GPIPRIMITIVES EQU 1
INCL_NOBASEAPI     EQU 1
INCL_SAADEFS       EQU 1
INCL_WINERRORS     EQU 1
INCL_WINPOINTERS   EQU 1
OS2_NOBASEAPI      EQU 1
OS2_NOPMAPI        EQU 1
        INCLUDE PMGRE.INC

DINCL_BITMAP       EQU 1
DINCL_ENABLE       EQU 1
        INCLUDE DRIVER.INC
        INCLUDE EXTERN.INC
        INCLUDE PROTOS.INC

        INCLUDE ASSERT.MAC
        include cursors.inc
        include pointer.inc
        include curstrc.inc

InnerExcludeTest PROTO SYSCALL

;/*
;** Prototypes for private functions
;*/

.DATA
EXTERNDEF CurData:CURSORSTRUCT
if SCAN_CNT EQ 768
EXTERNDEF EnumBankFlag:BYTE
endif

.CODE   
        SUBTITLE DeviceSetCursor Function
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSetCursor 
;*
;* DESCRIPTION   = This function is called from the PDI dispatch table as the  
;*                 GreDeviceSetCursor function.  The given pointer shape is    
;*                 saved in local storage to be used as the current pointer    
;*                 shape.  If the pointer to the pointer shape is NULL, then no
;*                 pointer is to be drawn.  The given pointer shape will have  
;*                 been converted from generic form into the dimensions        
;*                 requested by this driver.  Any pointer on the screen will be
;*                 removed before the new pointer shape is set.  The drawing of
;*                 the new pointer will be delayed until the check_pointer     
;*                 routine is called (check_pointer is the only routine that   
;*                 can make the pointer become visible).  If this routine is   
;*                 reentered, the request will be ignored.                     
;*                                                                             
;*                 Registers Preserved:                                                                   
;*                       SI,DI,DS,BP                                                                      
;*                 Registers Destroyed:                                                                   
;*                       AX,BX,CX,DX,ES,FLAGS                                                             
;*                                                                             
;* INPUT         = C Prototype:                                                  
;*                   BOOL SYSCALL DeviceSetCursor (HDC hdc,                                                                                  
;*                                                 PPOINTL pptHotspot,                                                                       
;*                                                 ULONG hbm,                                                                                
;*                                                 PVOID pInstance,                                                                          
;*                                                 ULONG lFunction);                                                                         
;*                                                                                                                                           
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE
;* RETURN-ERROR  = FALSE
;*
;**************************************************************************/

ALIGN 4
DeviceSetCursor PROC SYSCALL PUBLIC uses EBX ECX EDX,
                hdc       :HDC,
                pptHotspot:PPOINTL,
                hbm       :ULONG,
                pInstance :PVOID,
                lFunction :ULONG

        INVOKE  enter_driver_sem                 ; Acquire screen semaphore

IFDEF FIREWALLS
        MOV     EBX,hbm                          ; They must have passed us a valid
        CMP     EBX,0                            ; bitmap handle else the Engine
        JE      @F                               ; screwed up

        CMP     [EBX].BITMAP.bm_sd.sd_usId,SURFACE_IDENT
        JNE     DSCNotBitmap
        TEST    [EBX].BITMAP.bm_sd.sd_fb,SD_DEVICE
        JZ      @F

DSCNotBitmap:
        rip        text,<DeviceSetCursor was given an invalid bitmap>

@@:

ENDIF ; FIREWALLS

        CMP     hbm,0                   ; Look for null pointer
        JZ      DSCLookingGood
        MOV     EBX,pptHotspot          ; Validate hotspot offsets

        MOV     EAX,[EBX].POINTL.ptl_x
        MOVSX   EDX,AX
        cmp     EDX,EAX
        JNE     DSCInvCoordinate
        MOV     ECX,EAX
        MOV     EAX,[EBX].POINTL.ptl_y
        MOVSX   EDX,AX
        cmp     EDX,EAX
        JE      DSCLookingGood

DSCInvCoordinate:
        MOV     EAX,PMERR_INV_COORDINATE
        save_error_code
        XOR     EAX,EAX
        JMP     DSCExit
ALIGN 4

DSCLookingGood:
        INVOKE  SetDeviceCursor,ECX,EAX,hbm,0,0,pInstance

DSCExit:
        INVOKE  leave_driver
        fw_zero <ECX>

        RET

DeviceSetCursor ENDP
   
        SUBTITLE SetColorCursor Function
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = SetColorCursor 
;*
;* DESCRIPTION   = This function is equivalent to SetCursor except that it    
;*                 takes a color bitmap handle.  This function is called from 
;*                 the PDI dispatch table as the GreSetColorCursor function.  
;*                 The given pointer shape is saved in local storage to be    
;*                 used as the current pointer shape.  If pPointerInfo is     
;*                 NULL, the pointer is to be removed.  The given pointer     
;*                 shape will have been converted from generic form into the  
;*                 dimensions requested by this driver.  Any pointer on the   
;*                 screen will be removed before the new pointer shape is set.
;*                 The drawing of the new pointer will be delayed until the   
;*                 check_pointer routine is called (check_pointer is the only 
;*                 routine that can make the pointer become visible).         
;*                                                                            
;*                 Registers Preserved:                                                                  
;*                       SI,DI,DS,BP                                                                     
;*                 Registers Destroyed:                                                                  
;*                       AX,BX,CX,DX,ES,FLAGS                                                            
;*                                                                            
;* INPUT         = C Prototype:                                                
;*                   BOOL SYSCALL SetColorCursor (HDC          hdc,                                                                       
;*                                                PPOINTERINFO pPointerInfo,                                                              
;*                                                PVOID        pInstance,                                                                 
;*                                                ULONG        lFunction);                                                                
;*                                                                            
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE  
;* RETURN-ERROR  = FALSE 
;*
;**************************************************************************/

ALIGN 4
SetColorCursor PROC SYSCALL PUBLIC uses EBX ECX EDX EDI ESI,
                hdc         :HDC,
                pPointerInfo:DWORD,
                pInstance   :PVOID,
                lFunction   :ULONG

        INVOKE  enter_driver_sem                 ; Acquire screen semaphore
        MOV     EBX,pPointerInfo
        CMP     EBX,0                            ; Removing cursor from screen?
        JZ      SCCNullCursor                    ;  Y - Go do it
        MOV     EDI,[EBX].POINTERINFO.ptri_hbmColor

        assert  EDI,NE,0                         ; Must be non null bitmaps
        assert  [EBX].POINTERINFO.ptri_hbmPointer,NE,0

        INVOKE  GetDriverInfo,
                [EBX].POINTERINFO.ptri_hbmPointer,
                DI_HBITMAP,
                hdc                              ; EAX = Translated hbmPointer

        CMP     EAX,GPI_ALTERROR
        JZ      SCCInvCursor                     ; Return error

IFDEF FIREWALLS
        CMP     [EAX].BITMAP.bm_sd.sd_usId,SURFACE_IDENT
        JNE     SCCNotBM
        TEST    [EAX].BITMAP.bm_sd.sd_fb,SD_DEVICE
        JZ      @F
SCCNotBM:
        rip        text,<SetColorCursor was given an invalid bitmap>
@@:

ENDIF ; FIREWALLS

        XCHG    EDI,EAX                          ; EDI = Translated hbmPointer
                                                 ; EAX = Original hbmColor
        INVOKE  GetDriverInfo,
                EAX,
                DI_HBITMAP,
                hdc                              ; EAX = Translated hbmColor

        CMP     EAX,GPI_ALTERROR                 ; Error?
        JNZ     SCCGoodColorCursor               ;  N - Continue

SCCInvCursor:
        MOV     EAX,PMERR_INV_CURSOR_BITMAP
        save_error_code
        XOR     EAX,EAX
        JMP     SCCExit
ALIGN 4

SCCGoodColorCursor:

IFDEF FIREWALLS
        CMP     [EAX].BITMAP.bm_sd.sd_usId,SURFACE_IDENT
        JNE     SCCNotBitmap
        TEST    [EAX].BITMAP.bm_sd.sd_fb,SD_DEVICE
        JZ      @F
SCCNotBitmap:
        rip        text,<SetColorCursor was given an invalid bitmap>
@@:
ENDIF ; FIREWALLS

        MOV     EDX,EDI                          ; EDX = translated hbmPointer
        MOV     EDI,pPointerInfo
        MOV     EBX,[EDI].POINTERINFO.ptri_xHotspot
        MOV     ECX,[EDI].POINTERINFO.ptri_yHotspot

;/*
;** EDX = translated hbmPointer
;** EAX = translated hbmColor
;** EBX = x hotspot if cursor non null
;** ECX = y hotspot if cursor non null
;*/

        assert  EAX,NE,0                         ; a NULL near ptr means no color bitmap

SCCNullCursor:
        INVOKE  SetDeviceCursor,
                EBX,
                ECX,
                EDX,
                EAX,
                [EDI].POINTERINFO.ptri_fPointer,
                pInstance

SCCExit:
        INVOKE  leave_driver
        fw_zero <ECX>
        RET
SetColorCursor ENDP
   
        SUBTITLE SetDeviceCursor
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = SetDeviceCursor
;*
;* DESCRIPTION   = Common routine for DeviceSetCursor and SetColorCursor.  The
;*                 given pointer shape is saved in local storage to be used as
;*                 the current pointer shape.  If the pointer to the pointer  
;*                 shape (pbmPointer) is NULL, then no pointer is to be drawn.
;*                 The given pointer shape will have been converted from      
;*                 generic form into the dimensions requested by this driver. 
;*                 Any pointer on the screen will be removed before the new   
;*                 pointer shape is set.  The drawing of the new pointer will 
;*                 be delayed until the check_pointer routine is called       
;*                 (check_pointer is the only routine that can make the       
;*                 pointer become visible).                                   
;*                                                                            
;* INPUT         = C Prototype:                                       
;*                   BOOL SYSCALL SetDeviceCursor (LONG sHotX,                                                                   
;*                                                 LONG sHotY,                                                                   
;*                                                 HBITMAP pbmPointer,                                                           
;*                                                 HBITMAP pbmColor,                                                             
;*                                                 ULONG   fwFlags,                                                              
;*                                                 PDDC pDDC);                                                                   
;*                                                                                                                               
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = TRUE
;* RETURN-ERROR  = FALSE
;*
;**************************************************************************/

ALIGN 4
SetDeviceCursor PROC SYSCALL PRIVATE uses EBX ECX EDX ESI EDI,
                sHotX     :SDWORD,
                sHotY     :SDWORD,
                pbmPointer:HBITMAP,
                pbmColor  :HBITMAP,
                fwFlags   :DWORD,
                pDDC      :PDDC

        LOCAL   pBitsAndXor :DWORD,     ; Pointer to AND/XOR mask bits
                pBitsColor  :DWORD,     ; Pointer to color mask bits
                tmpcxPointer:DWORD,
                tmpcyPointer:DWORD

        PUSHFD                          ; Save flags
        CLD

;/*
;** Validate the incoming pointer shape.  If they passed us a NULL, then the
;** old cursor is to be removed, and no new cursor defined.  If they passed
;** anything else, validate it to be a bitmap in the correct format for us.
;*/

        MOV     pBitsAndXor,0           ; Initialize pointers for null bitmaps
        MOV     pBitsColor,0

;/*
;** pbmPointer must be a monochrome bitmap, of the correct width and height.
;** It is actually a double bitmap containing both the AND and XOR masks.
;** Therefore, the height given must be twice the actual image height.
;*/

        MOV     ESI,pbmPointer          ; We have confirmed that it's a bitmap
        OR      ESI,ESI
        JZ      SDCNullBitmap
        MOV     EAX,[ESI].BITMAP.bm_sd.sd_pBits
        MOV     pBitsAndXor,EAX
        MOV     EAX,PMERR_INV_CURSOR_BITMAP
        TEST    [ESI].BITMAP.bm_sd.sd_fb,SD_COLOR
        JNZ     SDCLogError

;/*
;** The driver may allow more than one pointer size.  Check that the given
;** bitmap has allowed dimensions.
;*/

        MOV     EBX,[ESI].BITMAP.bm_sd.sd_cx
        MOV     EDX,[ESI].BITMAP.bm_sd.sd_cy    ; Should be double-height 
        SHR     EDX,1                           ; because it has both the AND 
                                                ; and XOR masks.
        JC      SDCLogError
        MOV     ESI,[offset PtrSizes]
        MOV     ECX,[ESI][-(sizeof cPtrSizes)]  ; ECX = Ct. of valid ptr sizes
        assert  ECX,NE,0                        ; ESI -> list of valid ptr 
                                                ; sizes

PtrSizeLoop:
        CMP     EBX,[ESI]                       ; Valid cxPtr?
        JNE     WrongCX
        CMP     EDX,[ESI].PTRSIZE.PtrHeight
        JE      BitmapSizeIsValid

WrongCX:
        ADD     ESI,sizeof PTRSIZE              ; Point to next size
        LOOP    PtrSizeLoop
        JMP     SDCLogError                     ; Oops
ALIGN 4

BitmapSizeIsValid:                              ; EBX:EDX = validated pointer 
                                                ;           width:height
        MOV     tmpcxPointer,EBX                ; We don't dare change the 
                                                ; actual pointer size until 
        MOV     tmpcyPointer,EDX                ; we've called pointer_off

;/*
;** Validate pbmColor only if pbmPointer is not null.  pbmColor must be a color
;** bitmap of the correct width and height.
;*/

        MOV     EDI,pbmColor
        OR      EDI,EDI
        JZ      SDCLookingGood
        MOV     ESI,[EDI].BITMAP.bm_sd.sd_pBits
        MOV     pBitsColor,ESI
        assert  EAX,E,PMERR_INV_CURSOR_BITMAP
        TEST    [EDI].BITMAP.bm_sd.sd_fb,SD_COLOR
        JZ      SDCLogError
        CMP     [EDI].BITMAP.bm_sd.sd_cx,EBX
        JNE     SDCLogError
        CMP     [EDI].BITMAP.bm_sd.sd_cy,EDX
        JE      SDCLookingGood

SDCLogError:
        save_error_code
        XOR     EAX,EAX
        JMP     SDCExit
ALIGN 4

SDCLookingGood:
        DEC     EDX                             ; Map the Y into our hardware
        SUB     EDX,sHotY                                        ; coordinate system.  (invert 
        MOV     sHotY,EDX                       ; it)

;/*
;** All the bitmap stuff looks real good.  Take down the old pointer and then
;** see about setting this as the new one.
;*/

SDCNullBitmap:
        XOR     ECX,ECX                         ; Set screen busy
        XCHG    CurData.screen_busy,CL                           ; and get current status
        assert  ECX,NE,0                        ; Walt says it should never 
                                                ; happen
        .ERRNZ  IS_BUSY

;/*
;** Remove any old pointer.
;**
;** cxReal and cyReal are kept as the upper left corner of where the pointer is
;** to be drawn.  Since the hot spot might change with the pointer shape, the
;** hot spot must be added back into these locations.  After the new pointer
;** has been set, the hot spot can be subtracted out for it.
;*/

        MOV     CL,CurData.fbPtrFlags           ; Need old value for later
        OR      CL,CL                           ; Cursor on?
        JS      SDCCursorIsOff                  ;  N - Don't bother
        .ERRNZ  PTR_OFF-80h
        CLI                                     ;  Y - Don't want cxReal, 
                                                ;      cyReal changing
        XOR     EAX,EAX                         ; Zero old hot spot and add 
        XCHG    EAX,CurData.cxHot               ; it back to real [X,Y] 
        ADD     CurData.cxReal,EAX              ; coordinate
        XOR     EAX,EAX
        XCHG    EAX,CurData.cyHot
        ADD     CurData.cyReal,EAX
        STI                                     ; Allow interrupts
        TEST    CurData.fwPrevFlags,PTRI_ANIMATE ; Only skip if last pointer 
        JZ      SDCRemoveCursor                                  ; also was animated (full 
                                                ; sized)
        TEST    fwFlags,PTRI_ANIMATE                     ; Animating?
        JNZ     SDCCursorIsOff                  ;  Y - Don't clear old cursor

SDCRemoveCursor:
        LEA     EDI,CurData
        INVOKE  pointer_off,0,0                                  ; Remove old ptr from screen
        MOV     CurData.fbPtrFlags,PTR_OFF

SDCCursorIsOff:
        MOV     EAX,fwFlags
        MOV     CurData.fwPrevFlags,AX
        CMP     pBitsAndXor,0                   ; pBitsAndXor was set to zero
        JZ      SDCGoodExit                                      ; if a null bitmap was passed
                                                ; in

;/*
;** move_pointers saves the new ptr (AND/XOR masks and COLOR bm) in off-screen
;** memory (on most devices).  If any edges of the new pointer are transparent
;** then move_pointers may simply reduce the size of the stored bitmap and
;** associated exclusion rect.
;*/

        MOV     EBX,tmpcxPointer                ; Not used by CGA/EGA/VGA
        MOV     EDX,tmpcyPointer
        ; internal to this file
        INVOKE  move_pointers,pBitsAndXor,pBitsColor,fwFlags
        ; Returns EDX and EAX
        OR      EAX,EAX                         ; CX=CY=0 iff xparent pointer 
        JNZ     @F                              ; given
        OR      EDX,EDX
        JZ      SDCGoodExit                     ; given
@@:
        MOV     CurData.cxPointer,EAX                   ; Pointer width in bits
        MOV     CurData.cyPointer,EDX                   ; Pointer height in scans

;/*
;** Since the pointer must be drawn again (it wasn't a null pointer), we have
;** to draw it.  To do this, the pointer excluded flag will be set in
;** fbPtrFlags.  Only the timer code can bring the pointer back once it has
;** been excluded, and will do it when the next timer interrupt occurs.  This
;** minimizes the code that has to be written or duplicated in SetCursor!
;**
;** Also set up the new hot spot adjustments and adjust the pointer coordinate
;** for it.
;*/

        CLI                                     ; Don't want cxReal, cyReal 
                                                ; changing
        MOV     EAX,sHotX                       ;Set X hot spot adjustment
        MOV     CurData.cxHot,EAX
        SUB     CurData.cxReal,EAX              ; Adjust cxReal for hotspot
        MOV     EAX,sHotY                       ; Ditto for Y
        MOV     CurData.cyHot,EAX
        SUB     CurData.cyReal,EAX
        MOV     CurData.fbPtrFlags,PTR_EXCLUDED ; Show excluded, but not 
                                                ; hidden
        TEST    fwFlags,PTRI_ANIMATE
        JZ      SDCGoodExit
        MOV     CurData.fbPtrFlags,PTR_REDRAW   ; Cursor is animated type it 
                                                ; needs to be redrawn
        STI
        MOV     CurData.screen_busy,NOT_BUSY
        LEA     eax,CurData
        INVOKE  MoveCursor,8000h,8000h          ; Force cursor check

;/*
;** Whatever had to be done has been.  Restore the interrupt state to whatever
;** was set by the user and free the screen and make the screen available.
;*/

SDCGoodExit:
        MOV     EAX,1
        STI
        MOV     CurData.screen_busy,NOT_BUSY

SDCExit:
        fw_zero <ECX>

        POPFD                                   ; Restore flags
        RET

SetDeviceCursor ENDP
        SUBTITLE far_exclude Function
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = far_exclude  
;*
;* DESCRIPTION   = 
;*
;*        This function sets the pointer exclusion rectangle.                       
;*                                                                                  
;*        The pointer exclusion area is set to the passed value.  If the pointer    
;*        image is currently within the excluded area, it will be removed from the  
;*        screen.                                                                   
;*                                                                                  
;*        The given X coordinates will be rounded to the word size being used       
;*        (byte, word, dword).  This removes the adjustment for word size out of    
;*        the actual hit test code into the code that creates the exclusion         
;*        rectangle.  The left side will be rounded down and the right side will be 
;*        rounded up).                                                              
;*                                                                                  
;*        As an example, for bytes:                                                 
;*                                                                                  
;*                 top,left  ---------------------                                  
;*                          |                     |                                 
;*                          |                     |                                 
;*                          |                     |                                 
;*                          | Exclusion rectangle |                                 
;*                          |                     |                                 
;*                          |                     |                                 
;*                          |                     |                                 
;*                           ---------------------  right,bottom                    
;*                                                                                  
;*                                                                                  
;*               |L              |               |              R|                  
;*               |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|              
;*                                                                                  
;*                  left will always be at D7                                       
;*                  right will always be at D0                                      
;*                                                                                  
;*                                                                                  
;*         Exclude is not called by the interrupt pointer drawing code.             
;*                 
;*         Registers Preserved:                        
;*               BP                                    
;*         Registers Destroyed:                        
;*               AX,BX,CX,DX,SI,DI,DS,ES,FLAGS         
;*                 
;*                 
;* INPUT         = ECX = X coordinate of left edge              
;*                 EDX = Y coordinate of top edge               
;*                 ESI = X coordinate of right edge (inclusive) 
;*                 EDI = Y coordinate of bottom edge (inclusive)
;*                 
;* OUTPUT        = NONE                                  
;*                 Warning: Interrupts enables upon exit.
;*                 
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

_PtrCode32 SEGMENT DWORD PUBLIC USE32 'CODE'

ALIGN 4
far_exclude PROC SYSCALL PUBLIC USES EDI
        LOCAL   dwVdm:DWORD

if SCAN_CNT EQ 768
        CMP     EnumBankFlag,1          ;cursor already excluded
        JE      NoExcludeNeeded
endif
        mov     dwVdm,ebx               ; if EBX == 055555555h then this is VDM call
                                        ; don't fool with int's
        AND     ECX,PTR_ROUND_LEFT               ; Round left coordinate down
        OR      ESI,PTR_ROUND_RIGHT              ; Round right coordinate up
        MOV     EBX,8000h               ; Make any negative top/lefts 0
        CMP     ECX,EBX                 ; 'C' if positive number
        SBB     EAX,EAX
        AND     ECX,EAX
        CMP     EDX,EBX
        SBB     EAX,EAX
        AND     EDX,EAX
        MOV     CurData.ExcludeRect.rcl_xLeft,ECX       ; Set up exclusion rectangle
        MOV     CurData.ExcludeRect.rcl_yTop,EDX
        MOV     CurData.ExcludeRect.rcl_xRight,ESI
        MOV     CurData.ExcludeRect.rcl_yBottom,EDI
        MOV     CurData.ExcludeCt,RECT_PRES
        MOV     CL,PTR_OFF+PTR_EXCLUDED ; Set test mask for ExcludeTest

;/*
;** Inside the critical section, we'll jump to ExcludeTest rather than call,
;** thus avoiding a stack reference (the push of the return address).
;** Currently (1 Mar 89) the ring 2 stack is 4K bytes and is locked down in
;** memory.  If the stack size is ever increased without locking down more than
;** the first page, then we will still be protected from stack page faults.
;*/

        cmp     dwVdm,55555555h                 
        je      @F
        CLI                                     ; Hit test is critical code
@@:
        MOV     EAX,CurData.cxCell              ; Get current pointer x,y 
        MOV     EBX,CurData.cyCell              ; location
        MOV     EDX,offset HitTestReturn        ; Load return address
        lea     edi,CurData
        JMP     InnerExcludeTest
ALIGN 4

HitTestReturn:
        JNC     NoExcludeNeeded                  ; Hidden or already excluded
        JZ      NoExcludeNeeded                  ; Don't need to exclude

;/*
;** The pointer needs to be removed from the screen.  Show that the screen is
;** busy and then take the pointer down.  Since this is a pointer drawing
;** operation which will take some time, do it with interrupts enabled.
;*/

        XOR     ECX,ECX
        XCHG    CurData.screen_busy,CL          ; Set screen busy and save old state
        .ERRNZ  IS_BUSY
        MOV     CurData.fbPtrFlags,PTR_EXCLUDED ; Show pointer excluded
        cmp     dwVdm,55555555h                 
        je      @F
        STI                             ; Allow interrupts
@@:
        LEA     EDI,CurData
        PUSH    ECX
        INVOKE  pointer_off,0,0                          ; Remove pointer
        POP     EAX                     ; Restore screen busy state
        MOV     CurData.screen_busy,AL

NoExcludeNeeded:
        cmp     dwVdm,55555555h                 
        je      @F
        STI
@@:
        RET

far_exclude ENDP
        SUBTITLE far_unexclude Function
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = far_unexclude 
;*
;* DESCRIPTION   = The exclusion rectangle is removed.  The pointer will not
;*                 be redrawn since it might have to be taken down for the  
;*                 next call.  Redrawing the pointer will be left to the    
;*                 CheckCursor routine.                                     
;*                                                                          
;*                 Registers Preserved:                                                                  
;*                       AX,BX,CX,DX,Si,DI,BP                                                            
;*                 Registers Destroyed:                                                                  
;*                       DS                                                                              
;*                                                                          
;* INPUT         = C Prototype:                       
;*                   void SYSCALL far_unexclude (void)                                                         
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
far_unexclude PROC SYSCALL PUBLIC
if SCAN_CNT EQ 768
        CMP     EnumBankFlag,1          ;cursor must stay excluded
        JE      fu_end
        MOV     CurData.ExcludeCt,RECT_NOT_PRES
fu_end:
else
        MOV     CurData.ExcludeCt,RECT_NOT_PRES
endif


        RET

far_unexclude ENDP

ALIGN 4
SetScreenBusy PROC SYSCALL,
        ulState:BYTE
        MOV     AL,ulState
ifdef  IBMJ        ;IBMJ
 OR AL,AL
 JNZ NotBusy
@@:
 XCHG CurData.screen_busy,AL
 OR AL,AL
 JZ @B
 RET

NotBusy:
endif ;IBMJ        ;IBMJ
        MOV     CurData.screen_busy,AL
        RET
SetScreenBusy ENDP   

_PtrCode32 ENDS

ALIGN 4
CursorInit PROC SYSCALL
        CALL    GetVRAMR0Pointer
        MOV     CurData.pVRAMRing0,EAX
        RET
CursorInit ENDP


END
