;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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 = POINTER2.ASM
;*
;* DESCRIPTIVE NAME = More pointer related functions.
;*
;*
;* VERSION      V2.0
;*
;* DATE         10/25/91
;*
;* DESCRIPTION  More pointer related functions.
;*
;* FUNCTIONS    CreateMasks1Thru7
;*              move_pointers
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*****************************************************************************/

        .386P
        .MODEL FLAT,SYSCALL

INCL_GPIPRIMITIVES EQU 1
INCL_NOBASEAPI     EQU 1
INCL_SAADEFS       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 EGAFAM.INC
        INCLUDE POINTER.INC
        INCLUDE ASSERT.MAC
        include curstrc.inc
.DATA
EXTERNDEF CurData:CURSORSTRUCT
.CODE
        SUBTITLE CreateMasks1Thru7
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = CreateMasks1Thru7
;*
;* DESCRIPTION   =
;*        The pointer shape has been copied into our memory.  Now pre-rotate the
;*        pointer for all the different alignments.  Simply put:
;*
;*                       pointer image              fill byte
;*
;*             |ABCDEFGH|IJKLMNOP|QRSTUVWX|YZabcdef|00000000|
;*
;*       becomes this for (x MOD 8) = 1
;*
;*             |0ABCDEFG|HIJKLMNO|PQRSTUVW|XYZabcde|f0000000|
;*
;*       and this for (x MOD 8) = 2
;*
;*             |00ABCDEF|GHIJKLMN|OPQRSTUV|WXYZabcd|ef000000|
;*
;*       Registers Preserved:
;*             BX,SI,DS,ES,BP
;*       Registers Destroyed:
;*             AX,CX,DX,DI
;*
;* INPUT         = EDI --> First byte of mask for phase alignment 1
;*                 EDX --> First byte of mask for phase alignment 0
;*                 ECX  =  (MASK_LENGTH * 7) / (WORK_WIDTH * 2)
;*                 AL   =  Fill value (00 or FFh)
;*
;* OUTPUT        = EDI --> First byte following end of mask for phase alignment 1
;*                 EDX --> First byte following end of mask for phase alignment 0
;*                 ECX  =  0
;*                 EAX  =  Unknown
;*
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

CreateMasks1Thru7 PROC SYSCALL PRIVATE

;/*
;** Since the masks are contiguous, we can do it as one very long loop,
;** where the results of rotating the previous mask by one becomes the
;** source for the next rotate by one.
;*/

        XCHG    ESI,EDX
        ADD     AL,AL   ; Set initial 'C' value

Rotate_next_two_scans:
        LODSW
        RCR     AL,1
        RCR     AH,1
        STOSW

        LODSW
        RCR     AL,1
        RCR     AH,1
        STOSW

        LODSW
        RCR     AL,1
        RCR     AH,1
        STOSW

        LODSW
        RCR     AL,1
        RCR     AH,1
        STOSW

        LODSW
        RCR     AL,1
        RCR     AH,1
        STOSW

        LOOP    Rotate_next_two_scans
        .ERRNZ  (WORK_WIDTH*2)-10

        XCHG    ESI,EDX

        RET

CreateMasks1Thru7 ENDP

        SUBTITLE move_pointers
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = move_pointers
;*
;* DESCRIPTION   =
;*   The AND, XOR and COLOR pointer masks are stored in the pointer work
;*   areas.  The original mask will be pre-rotated for all eight possible
;*   alignments within a byte.
;*
;*   As the pointer is copied, it will be processed to see if it can be made
;*   narrower.  After it has been copied, it will be processed to see if it
;*   can be made shorter.
;*
;*   The following table indicates how the XOR/AND bitmap interacts with the
;*   COLOR bitmap for a color system:
;*
;*        XOR  AND  COLOR  Result
;*        1     1     x    invert screen
;*        0     0     x    use x
;*        0     1     x    transparent
;*        1     0     x    use x
;*
;*   From the table, we observe that when the AND bits are on, the
;*   corresponding COLOR bits are irrelevant.  We preprocess the COLOR bitmap
;*   to mask off these bits.
;*
;*   When drawing the color pointer, we do the following steps:
;*        1. XOR the destination with XOR mask.
;*        2. AND the destination with AND mask.  Note the zero bits would
;*           mask off the destination to prepare for the COLOR mask.
;*        3. OR the destination with the COLOR mask.  Note it does not affect
;*           the inverted or transparent bits since we have masked off the
;*           corresponding COLOR bits during preprocessing.
;*
;*       Registers Preserved:
;*             BP
;*       Registers Destroyed:
;*             AX,BX,CX,DX,SI,DI,DS,ES,FLAGS
;*
;* INPUT         = C Prototype:
;*                   ULONG move_pointers (ULONG  pBitsAndXor,
;*                                        ULONG  pBitsColor,
;*                                        USHORT wFlags);
;*
;*                    where:
;*                      pBitsAndXor points to the AND/XOR masks.
;*                      pBitsColor  points to the color mask.
;*                      wFlags      indicates the type of pointer and is one of
;*                                  the  following:
;*                                    FBPTR_COLOR if color pointer
;*                                    0           if mono pointer
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = 32-bit value consisting of two 16-bit fields.  The
;*                 high-order word contains the height in scan lines to be
;*                 used for the exclusion hit test, while the low-order word
;*                 contains the width in pels to be used for the exclusion
;*                 hit test.
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


move_pointers PROC SYSCALL PUBLIC uses EBX ECX EDX EDI ESI,
                pBitsAndXor:DWORD,
                pBitsColor :DWORD,
                fwFlags    :DWORD
        CLD

;/*
;** The image we are copying is PTR_WIDTH bytes wide.  We must add an extra
;** byte to make it WORK_WIDTH wide.  The byte we add depends on whether this
;** is the AND or the XOR mask.  For an AND mask, we add an FF byte on the end
;** of each scan.  For an XOR mask, we add a 00 byte on the end of each scan.
;** For the COLOR mask, we add a 00 byte on the end of each scan of all
;** planes.  These bytes won't alter anything on the screen.
;*/

;/*
;** Copy the AND mask over.  As we copy it, accumulate the value of each
;** column of the mask.  If the entire column is FF, we may be able to discard
;** it.
;*/

        MOV     CurData.fbPointer,0                     ; Assume it's a b/w pointer
        LEA     EDI,CurData.BaseAndMasks
        MOV     ECX,PTR_HEIGHT                  ; Set height for move
        MOV     EAX,0FFFFFFFFh                  ; Init. mask column accum.
        MOV     ESI,pBitsAndXor                 ; ESI --> AND/XOR mask

Move_next_AND_mask_scan:
        rep movsd                                   ; Move explicit part
        .ERRNZ  PTR_WIDTH-4

;/*
;** Copy the XOR mask over.  As we copy it, accumulate the value of each
;** column of the mask.  If the entire column is 00, we may be able to discard
;** it.
;*/

        MOV     ECX,PTR_HEIGHT          ; Set height for move
        xor     eax,eax
Move_next_XOR_mask_scan:
        rep movsd                           ; Move explicit part
        .ERRNZ  PTR_WIDTH-4

;/*
;** copy the COLOR mask over.  As we copy it, mask off the
;** corresponding AND bits in the COLOR mask since we do not use that
;** color bit if the AND bit is on.
;**
;*/

        mov     ecx,pBitsColor          ;Set DS:SI --> color bitmap bits
        or      ecx,ecx
        jnz     @f
        jmp     mcp_done
@@:
        mov     CurData.fbPointer, FBPTR_COLOR   ; indicate a color cursor
        mov     esi,ecx
        LEA     edi,CurData.BaseColorMasks

        mov     eax, PTR_WIDTH * 8               ; ax = width of color mask in bytes
        mov     ecx, PTR_HEIGHT                   ; cx = height of color mask in scans
        mul     ecx                               ; ax = size of color mask in bytes
        shr     eax, 2                            ; ax = size of color mask in words
        mov     ecx, eax
        rep     movsd                             ; Move the color mask over

;/*
;** Now go through the color mask setting the bytes
;** to 0 where a corresponding AND mask bit is set.
;**------------------------------------
;**       XOR     AND                      COLOR
;**       1       1                        invert screen
;**       0       0                        use color
;**       0       1                        transparent
;**       1       0                        use color
;**
;** Register usage in loop
;** esi = color mask source ptr
;** edi = color mask dest ptr
;** ebx = AND mask source ptr
;** ecx   = color mask byte counter
;** dh    = test bit register
;** dl    = AND mask cache register
;** al    = color mask data
;** ah    = 0
;*/

        lea     edi, CurData.BaseColorMasks   ; set up the pointers
        lea     esi, CurData.BaseColorMasks
        lea     ebx, CurData.BaseAndMasks

        mov     ecx, PTR_WIDTH * 8 * PTR_HEIGHT  ; Set the count
        mov     dh, 80h                           ; set the test bit
        mov     ah, 0                             ; set the replacement value

        mov     dl, byte ptr [ebx]                ; dl = first byte of AND mask
        inc     ebx                               ; bx = ptr to next byte of AND mask
mcp_loop:
        lodsb                                     ; al = byte from color mask
        test    dl, dh                            ; is there a corresponding AND bit set
        jz      @f
        mov     al, ah                            ; AND bit was set, replace value with 0
@@:
        stosb                                     ; replace the color mask byte
        ror     dh, 1                             ; rotate the AND mask test bit right
        jnc     @f                                ; are we done with the byte?
        mov     dl, [ebx]                         ; dl = new byte of AND mask
        inc     ebx                               ; bx = ptr to next byte
@@:
        loop    mcp_loop                          ; loop though the entire color mask

mcp_done:                                         ; Move Color Pointer Done

TrimPointer:

;/*
;** First trim the columns.
;**
;** Init the AndSumArray and the XorSumArray
;*/

        mov     eax, -1
        lea     edi, CurData.AndSumArray
        stosd

        mov     eax, 0
        lea     edi, CurData.XorSumArray
        stosd

;/*
;** AND each col of the AND mask into one of the entries of the SumArray
;*/

        mov     ebx, 0
        lea     esi, CurData.BaseAndMasks
        mov     ecx, PTR_HEIGHT * PTR_WIDTH
@@:
        lodsb
        and     byte ptr CurData.AndSumArray[ebx], al
        inc     ebx
        and     ebx, 3
        loop    @b

;/*
;** OR each col of the XOR mask into one of the entries of the SumArray
;*/

        mov     ebx, 0
        lea     esi, CurData.BaseXorMasks
        mov     ecx, PTR_HEIGHT * PTR_WIDTH
@@:
        lodsb
        or      byte ptr CurData.XorSumArray[ebx], al
        inc     ebx
        and     ebx, 3
        loop    @b

;/*
;** The first non-FF byte in the AND sum or the first non-0 byte
;** in the XOR sum in the right hand col.
;*/

        std
        mov     al, 0FFh
        mov     cx, 4
        lea     edi, CurData.AndSumArray[3]
        repe    scasb
        mov     dl, cl                            ; dl = right AND col

        mov     al, 0
        mov     cx, 4
        lea     edi, CurData.XorSumArray[3]
        repe    scasb
        mov     dh, cl                            ; dh = right XOR col
        cld

;/*
;** Set the right edge of the cursor
;*/

        mov     al, dh
        cmp     dh, dl
        jge     @f
        mov     al, dl
@@:
        inc     al
        cbw
        mov     CurData.PtrWidthBytes, ax

;/*
;** Set the Pointer Width for all the masks and pointer size.
;*/

        mov     CurData.PtrXorMask.sizs_cx, ax
        mov     CurData.PtrAndMask.sizs_cx, ax
        shl     ax, 3
        mov     CurData.PtrColorMask.sizs_cx, ax
        mov     CurData.PtrSizeBytes.sizs_cx, ax

;/*
;** Now trim the Rows
;** Init the AndSumArray and the XorSumArray
;*/

        mov     eax, -1
        lea     edi, CurData.AndSumArray
        mov     ecx, PTR_HEIGHT / 4
        rep     stosd

        mov     eax, 0
        lea     edi, CurData.XorSumArray
        mov     ecx, PTR_HEIGHT / 4
        rep     stosd

;/*
;** AND each row of the AND mask into one of the entries of the SumArray
;*/

        mov     ebx, 0                                ; init AndSumArray index
        mov     dh, PTR_HEIGHT                        ; init row counter
        lea     esi, CurData.BaseAndMasks ; si = AND mask pointer
        mov     ecx, PTR_WIDTH                        ; cx = column counter
@@:
        lodsb                                         ; al = byte from AND mask
        and     byte ptr CurData.AndSumArray[ebx], al     ; AND into sum array
        loop    @b                                    ; do the entire row
        dec     dh                                    ; bump the row counter
        jz      @f                                    ; exit if all rows are processed
        inc     ebx                                   ; bump the SumArray row index
        mov     ecx, PTR_WIDTH                        ; reset the col counter
        jmp     @b                                    ; do the next row
@@:

;/*
;** OR each col of the XOR mask into one of the entries of the SumArray
;*/


        mov     ebx, 0                                ; init XorSumArray index
        mov     dh, PTR_HEIGHT                        ; init row counter
        lea     esi, CurData.BaseXorMasks ; si = XOR mask pointer
        mov     ecx, PTR_WIDTH                        ; cx = column counter
@@:
        lodsb                                         ; al = byte from XOR mask
        or      byte ptr CurData.XorSumArray[ebx], al     ; OR into sum array
        loop    @b                                    ; do the entire row
        dec     dh                                    ; bump the row counter
        jz      @f                                    ; exit if all rows are processed
        inc     ebx                                   ; bump the SumArray row index
        mov     ecx, PTR_WIDTH                        ; reset the col counter
        jmp     @b                                    ; do the next row
@@:

;/*
;** The first non-FF byte in the AND sum or the first non-0 byte
;** in the XOR sum in the right hand col.
;*/

        std
        mov     al, 0FFh
        mov     ecx, PTR_HEIGHT
        lea     edi, CurData.AndSumArray[PTR_HEIGHT-1]
        repe    scasb
        mov     dl, cl                            ; dl = bottom AND col

        mov     al, 0
        mov     ecx, PTR_HEIGHT
        lea     edi, CurData.XorSumArray[PTR_HEIGHT-1]
        repe    scasb
        mov     dh, cl                            ; dh = bottom XOR col
        cld

;/*
;** Set the bottom of the cursor
;*/

        mov     al, dh
        cmp     dh, dl
        jge     @f
        mov     al, dl
@@:
        inc     al
        cbw
        mov     CurData.PtrHeightBytes, ax

        ; Initialize all the height fields of the Cursor and Mask stuctures

        mov     CurData.PtrXorMask.sizs_cy, ax
        mov     CurData.PtrAndMask.sizs_cy, ax
        mov     CurData.PtrColorMask.sizs_cy, ax
        mov     CurData.PtrSizeBytes.sizs_cy, ax
        mov     eax,CurData.cxPointer
        mov     edx,CurData.cyPointer


move_color_pointer_done:
        ret
move_pointers ENDP
        END

