;*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.;
;*****************************************************************************/
        PAGE     55,132
        TITLE    Correlation Functions
        SUBTITLE Header

;/*****************************************************************************
;*
;* SOURCE FILE NAME = MAJOR0B.ASM
;*
;* DESCRIPTIVE NAME = Control Functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/25/91
;*
;* DESCRIPTION  Control Functions
;*
;* FUNCTIONS  Public:
;*              correlate_for_point_si
;*              GetPickWindow
;*              intersect_rcl
;*              recalc_correlate_rect
;*              SetPickWindow
;*            Private:
;*              QueryCharCorr
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   12/05/87                     Hock Lee [hockl] No longer clip pick window
;*                                against graphics fields and viewing limit
;*                                since all correlations will be done against clip
;*                                regions which include them.
;*   06/17/91                     Hock Lee [hockl] Allow full 16 bit coordinates
;*                                pick window in device space. Truncate pick window
;*                                if overflow is the result of DC origin offset.
;*   11/25/91                     Re-Written by Micrografx
;*
;*****************************************************************************/

        .386P
        .MODEL FLAT,SYSCALL

;/*
;** Included files
;*/

INCL_DDICOMFLAGS   EQU 1
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 ASSERT.MAC
        include tune.inc
;/*
;** Private functions
;*/

        .CODE

IFDEF USECHARCORR

        SUBTITLE QueryCharCorr
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = QueryCharCorr
;*
;* DESCRIPTION   = This function returns an offset indicating which character
;*                 within a character string was selected, the last time a
;*                 character string primitive returned a successful correlation hit.
;*                 If more than one character in the string was selected, the
;*                 offset of the first is returned.
;*
;*                 A value of zero indicates the first character in the string.
;*                 A negative value indicates that no string has been correlated on.
;*
;*                 Registers Destroyed:
;*                         AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   LONG _syscall QueryCharCorr (HDC hdc, PVOID pInstance,
;*                                                ULONG lFunction);
;*
;*                    where:
;*                      hdc --> DDC
;*                      pInstance --> Instance data
;*                      lFunction  -  HOW = Flags, LOW = Function
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = 0
;* RETURN-ERROR  = 1 -- Error occurred.
;*                 2 -- No correlation hit.
;**************************************************************************/

ALIGN 4
QueryCharCorr PROC SYSCALL PRIVATE USES edi esi,
                hdc       :HDC,
                pInstance :PVOID,
                lFunction :DWORD

        DebugMsg <Entering MAJOR0B.QueryCharCorr,Private,KEZ>

        MOV        ESI,pInstance                    ; ESI --> DDC
        MOV        EAX,[ESI].ddc_char_corr_offset   
                                                    
                                                    
                                                    
        MOV        ECX,EAX

        DebugMsg <Leaving QueryCharCorr>

        RET

QueryCharCorr ENDP

ENDIF; USECHARCORR

;/*
;** Public functions
;*/

        SUBTITLE GetPickWindow
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = GetPickWindow
;*
;* DESCRIPTION   = This function is invoked from the dispatch table in response to a
;*                 call to the GreGetPickWindow function and returns the position
;*                 and size of the pick window, in page coordinate space.
;*
;*                 Registers Destroyed:
;*                         AX,BX,CX,DX,ES
;*
;* INPUT         = C Prototype:
;*                   BOOL _syscall GetPickWindow (HDC    hdc,
;*                                                PRECTL pPick,
;*                                                PVOID  pInstance,
;*                                                ULONG  lFunction);
;*
;*                    where:
;*                      All arguments are as specified for the GreGetPickWindow
;*                      function.
;*
;* OUTPUT        = As specified for the GreGetPickWindow function.
;*
;* RETURN-NORMAL = As specified for the GreGetPickWindow function.
;* RETURN-ERROR  = As specified for the GreGetPickWindow function.
;*
;**************************************************************************/

ALIGN 4
GetPickWindow PROC SYSCALL PUBLIC uses EDI ESI EBX,
                hdc      :HDC,
                pPick    :PRECTL,
                pInstance:PVOID,
                lFunction:ULONG

        DebugMsg <Entering MAJOR0B.GetPickWindow,DISPATCH,KEZ>

        CLD
        MOV        ESI,pInstance                ; ESI --> DDC
        MOV        EDX,ESI                 ; EDX --> DDC
        INVOKE        enter_driver
        JC        GPW_Exit_no_lock        ; EAX = 0 on error
        MOV        EDI,pPick                ; EDI = pPick
        MOV        ESI,[ESI].DDC.ddc_prddc
        rddc?        ESI
        ADD        ESI,RDDC.rddc_rclPick        ; ESI --> ddc_pick_window
        MOV        ECX,(sizeof RECTL) / 4
        .ERRNZ        (sizeof RECTL) and 3
    REP        MOVSD
        MOV        EAX,1                        ; Show succes

GetPickWindow_exit:
        INVOKE        leave_driver

GPW_Exit_no_lock:
        MOV        ECX,EAX

        DebugMsg <Leaving GetPickWindow>

        RET

GetPickWindow ENDP

_TUNE2 segment DWORD FLAT PUBLIC 'CODE'
        SUBTITLE SetPickWindow
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = SetPickWindow
;*
;* DESCRIPTION   = This sets the position and size of the pick window, in page
;*                 coordinate space, for subsequent correlation operations.
;*                 The boundary of the pick window is included in the area
;*                 correlated upon.
;*                 The driver is responsible for keeping the pick window.  It must
;*                 be maintained in PAGE coordinates so that there is no round off
;*                 error between a SetPickWindow and a GetPickWindow.
;*
;*                 The driver's internal convention is that we ONLY use the current
;*                 pick window in SCREEN coordinates, which are clipped to viewing
;*                 limits and graphics field and kept in ddc_corr_rect.
;*                 The ddc_fb[0] byte will have the DDC_CORR_INV
;*                 bit set if the clip region changes.
;*
;*                 Registers Destroyed:
;*                         AX,BX,CX,DX,ES
;*
;* INPUT         = lpPickWindow - Points to an array containing the minimum
;*                       and maximum xy coordinate pairs of the window:
;*                       (s32_xmin, s32_ymin, s32_xmax, s32_ymax).
;*                       The data in the array may be overwritten.
;*
;*
;*
;*
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1
;* RETURN-ERROR  = AX = 0 (ERROR_WINDOW_LIMS_OUTSIDE_PAGE)
;*
;**************************************************************************/

ALIGN 4
SetPickWindow PROC SYSCALL PUBLIC uses EBX EDI ESI,
                hdc          :HDC,
                pPick        :PRECTL,
                pInstance    :PVOID,
                FunN         :ULONG

        LOCAL        CorrRect     :RECTL
        LOCAL        ViewLimits   :RECTL
        LOCAL        GraphicsField:RECTL

        DebugMsg <Entering MAJOR0B.SetPickWindow,DISPATCH,KEZ>

IFDEF FIREWALLS

;/*
;** Since GPI will not call us with     rectangle, we have a firewall instead.
;*/

        MOV        EBX,pPick
        MOV        EAX,[EBX].RECTL.rcl_xRight        ; Make sure right >= left
        SUB        EAX,[EBX].RECTL.rcl_xLeft
        JNS        Pick_window_x_ok
        rip        text,<bad pick window>

Pick_window_x_ok:
        MOV        EAX,[EBX].RECTL.rcl_yTop        ; Make sure top >= bottom
        SUB        EAX,[EBX].RECTL.rcl_yBottom
        JNS        Pick_window_y_ok
        rip        text,<bad pick window>

Pick_window_y_ok:

ENDIF ; FIREWALLS

        CLD
        MOV        EDX,pInstance
        INVOKE  enter_driver
        JC        SPW_Exit_no_lock                ; EAX = 0 on error
        no_path_area        SetPickWindow_exit,both

;/*
;** Transform the coordinates in local space so we don't wipe out what we were
;** passed in.
;*/

        MOV        ESI,pPick
        LEA        EDI,CorrRect                        ; EDI --> CorrRect
        MOV        ECX,(sizeof RECTL) / 4
        .ERRNZ  (sizeof RECTL) and 3
    REP MOVSD                                        ; fill in temporary rectangle
        MOV        ESI,pInstance                        ; ESI --> DDC

;/*
;** Transform pick window to DEVICE coordinates.
;*/

        LEA        EDI,CorrRect                        ; EDI -> CorrRect
        INVOKE        convert_page_device,EDI,2        ; ESI --> DDC
        OR        EAX,EAX
        JZ        SetPickWindow_exit                ; Return error

;/*
;** Transform pick window to SCREEN coordinates.  If there is an overflow caused
;** by DC origin offset, maxout or minout the coordinates.
;*/

        INVOKE        convert_device_screen,EDI,2        ; ESI --> DDC
        XOR     EDX,EDX
        OR        EAX,EAX
        JNZ        @F
        INC        EDX                                ; Overflow 16 bits

@@:

;/*
;** Make right/top exclusive.
;*/

        ADD        WORD ptr CorrRect.rcl_xRight,1
        JNO        @F
        INC        EDX                                ; Overflow 16 bits

@@:
        ADC        WORD ptr CorrRect.rcl_xRight+2,0
        ADD        WORD ptr CorrRect.rcl_yTop,1
        JNO        @F
        INC        EDX                                ; Overflow 16 bits

@@:
        ADC        WORD ptr CorrRect.rcl_yTop+2,0
        OR         EDX,EDX                                ; Did we overflow 16 bits?
        JZ         Got_pick_window                        ;  N - Continue
        INVOKE     truncate_rectl                         ;  Y - Maxout and minout
                                                          ;      coordinates

Got_pick_window:
        MOV        EAX,CorrRect.rcl_xLeft
        MOV        EBX,CorrRect.rcl_xRight
        CMP        EAX,EBX
        JZ        Null_pick_window                ; We have a null pick window
        MOV        ECX,CorrRect.rcl_yBottom
        MOV        EDX,CorrRect.rcl_yTop
        CMP        ECX,EDX
        JZ        Null_pick_window                ; We have a null pick window

;/*
;** We have checked cross-over above, just to be sure.
;*/

        assert        EAX,L,EBX                       ; Make sure it's well-ordered
        assert        ECX,L,EDX

        ddc?        ESI
        MOV        EDI,[ESI].DDC.ddc_prddc                ; EDI --> RDDC
        rddc?        EDI

;/*
;** Store the resulting pick window in the DDC.
;*/

        LEA        EDI,[EDI].RDDC.rddc_rcsCorr        ; EDI = rddc_rcsCorr
        STOSD                                        ; Left
        XCHG        EAX,ECX
        STOSD                                        ; Bottom
        XCHG        EAX,EBX
        STOSD                                        ; Right
        XCHG        EAX,EDX
        STOSD                                        ; Top

;/*
;** Save the pick window passed in.
;*/

        .ERRNZ        RDDC.rddc_rclPick GT RDDC.rddc_rcsCorr
        ADD        EDI,RDDC.rddc_rclPick-RDDC.rddc_rcsCorr-(sizeof RECTL)
                                                ; EDI --> rddc_rclPick
        MOV        EBX,ESI                                ; EBX --> DDC
        MOV        ESI,pPick                        ; ESI --> pPick
        MOV        ECX,(sizeof RECTL) / 4
        .ERRNZ        (sizeof RECTL) and 3
    REP MOVSD

;/*
;** Now we trust them!
;*/

        ddc?        EBX
        AND        [EBX].DDC.ddc_fb[0],not DDC_CORR_INV
        JMP        SetPickWindow_good_exit
ALIGN 4

;/*
;** Resulting pick window is null
;*/

Null_pick_window:
        MOV        EAX,PMERR_INV_PICK_APERTURE_POSN        
        save_error_code
        XOR        EAX,EAX
        JMP        SetPickWindow_exit
ALIGN 4

SetPickWindow_good_exit:
        MOV        EAX,1

SetPickWindow_exit:
        INVOKE        leave_driver

SPW_Exit_no_lock:
        MOV        ECX,EAX        ; recalc_correlate_rect depends on ECX return value

        DebugMsg <Leaving SetPickWindow>

        RET

SetPickWindow ENDP
        SUBTITLE recalc_correlate_rect
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = recalc_correlate_rect
;*
;* DESCRIPTION   = Recalculates the correlate rectangle (ddc_rcsCorr) using the
;*                 current pick window only when clip region or transformation
;*                 change.
;*
;*                 Registers Preserved:
;*                        SI,DI,DS,BP
;*                 Registers Destroyed:
;*                        AX,BX,CX,DX,ES,FLAGS
;* INPUT         = ESI --> DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = ECX = 1        Success
;*                 EAX = ECX = 0        Null pick window
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
recalc_correlate_rect PROC SYSCALL PUBLIC USES esi edi

        DebugMsg <Entering MAJOR0B.recalc_correlate_rect,Public,KEZ>

        ddc?        ESI

;/*
;** Call SetPickWindow to recalculate ddc_rcsCorr rectangle.
;*/

        MOV        EAX,[ESI].DDC.ddc_prddc
        ADD        EAX,RDDC.rddc_rclPick        ; EAX --> Pick window
        INVOKE        SetPickWindow,[ESI].DDC.ddc_hdc,EAX,ESI,0
        assert        EAX,E,ECX                ; SetPickWindow returns ECX

        DebugMsg <Leaving recalc_correlate_rect>

        RET

recalc_correlate_rect ENDP
_TUNE2 ENDS
        SUBTITLE correlate_for_point_si
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = correlate_for_point_si
;*
;* DESCRIPTION   = This function performs a correlation against the correlation
;*                 rectangle and the given point.
;*
;* INPUT         = EBX  =  X coordinate of the poin
;*                 EDX  =  Y coordinate of the poin
;*                 ESI --> DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1 if no correlation hit
;*                 EAX = 2 if correlation hit
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
correlate_for_point_si PROC SYSCALL PUBLIC USES esi,

        DebugMsg <Entering MAJOR0B.correlate_for_point_si,Public,KEZ>

        ddc?       ESI
        TEST       [ESI].DDC.ddc_fb,DDC_CORR_INV
        JZ         Do_correlate                       ; Has corr rect in DDC
        PUSH       EBX                                ; Save point
        PUSH       EDX
        INVOKE     recalc_correlate_rect              ; Set the corr rect
        POP        EDX                                ; Restore point
        POP        EBX
        JECXZ      CFP_Si_no_hit                      ; Null pick window

Do_correlate:
        MOV        EAX,2                              ; Assume hit
        MOV        ESI,[ESI].DDC.ddc_prddc
        rddc?      ESI
        CMP        EBX,[ESI].RDDC.rddc_rcsCorr.rcl_xLeft
        JL         CFP_Si_no_hit
        CMP        EBX,[ESI].RDDC.rddc_rcsCorr.rcl_xRight
        JGE        CFP_Si_no_hit
        CMP        EDX,[ESI].RDDC.rddc_rcsCorr.rcl_yTop
        JGE        CFP_Si_no_hit
        CMP        EDX,[ESI].RDDC.rddc_rcsCorr.rcl_yBottom
        JGE        CFP_Si_exit                        ; We have a hit here

CFP_Si_no_hit:
        MOV        EAX,1

CFP_Si_exit:

        DebugMsg <Leaving correlate_for_point_si>

        RET

correlate_for_point_si ENDP

        SUBTITLE intersect_rcl
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = intersect_rcl
;*
;* DESCRIPTION   = Takes the intersection of two RECTLs.  Overwrites the
;*                 destination RECT with the intersection.  Assumes both RECTLs
;*                 are well ordered.
;*
;*                 Registers Destroyed:
;*                        BX,CX,DX
;*
;* INPUT         = ESI --> source RECTL
;*                 EDI --> dest RECTL
;*                 EBX = check for null rect on result?
;* OUTPUT        =
;*
;* RETURN-NORMAL = if EBX = 1 on entry
;*                    EAX = 0 null rect otherwise AX = 1
;*                 else
;*                    nothing
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
intersect_rcl PROC SYSCALL PUBLIC

        DebugMsg <Entering MAJOR0B.intersect_rcl,Public,KEZ>

;/*
;** Get the max left.
;*/

        PUSH        EBX
        MOV        EAX,[EDI].RECTL.rcl_xLeft
        MOV        EBX,[ESI].RECTL.rcl_xLeft
        smax_ax EBX
        MOV        [EDI].RECTL.rcl_xLeft,EAX

;/*
;** Get the min right.
;*/

        MOV        EAX,[EDI].RECTL.rcl_xRight
        MOV        EBX,[ESI].RECTL.rcl_xRight
        smin_ax EBX

;/*
;** Make sure X is well ordered.
;*/

        MOV        EBX,[EDI].RECTL.rcl_xLeft
        smax_ax EBX
        MOV        [EDI].RECTL.rcl_xRight,EAX

;/*
;** Get the max bottom.
;*/

        MOV        EAX,[EDI].RECTL.rcl_yBottom
        MOV        EBX,[ESI].RECTL.rcl_yBottom
        smax_ax EBX
        MOV        [EDI].RECTL.rcl_yBottom,EAX
;/*
;** Get the min top.
;*/

        MOV        EAX,[EDI].RECTL.rcl_yTop
        MOV        EBX,[ESI].RECTL.rcl_yTop
        smin_ax EBX

;/*
;** Make sure Y is well ordered.
;*/

        MOV        EBX,[EDI].RECTL.rcl_yBottom
        smax_ax EBX
        MOV        [EDI].RECTL.rcl_yTop,EAX
        POP        EBX
        CMP        EBX,1
        JNE        Intersect_rcl_exit
        MOV        EAX,[EDI].RECTL.rcl_xLeft
        CMP        EAX,[EDI].RECTL.rcl_xRight                ; Is left < right?
        JGE        Return_null_rect                ;  N - Null rect
        MOV        EAX,[EDI].RECTL.rcl_yBottom           ;  Y - Is bottom < top?
        CMP        EAX,[EDI].RECTL.rcl_yTop
        JGE        Return_null_rect                ;  N - Null rect
        MOV        EAX,1                                ;  Y - Return clip rect
        JMP        Intersect_rcl_exit
ALIGN 4

;/*
;** Return null intersection.
;*/

Return_null_rect:
        MOV        EBX,EDI                         ; Save EDI
        MOV        ECX,(sizeof RECTL) / 4          ; Set rectangle's values to 0
        XOR        EAX,EAX
    REP STOSD
        MOV        EDI,EBX                         ; Restore EDI

Intersect_rcl_exit:

        DebugMsg <Leaving intersect_rcl>

        RET

intersect_rcl ENDP

        SUBTITLE intersect_with_corr
        PAGE +

;/***************************************************************************
;*
;* FUNCTION NAME = intersect_with_corr
;*
;* DESCRIPTION   = Intersects the destination rectangle with the correlation
;*                 rectangle.
;*
;*                 Registers Destroyed:
;*                        AX,BX,CX,DX
;*
;* INPUT         = C Prototype:
;*                   ULONG _syscall intersect_with_corr (PRECTL pDestination);
;*
;*                    where:
;*                      pDestination --> Destination rectangle.
;*                      ESI --> DDC
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1 if correlation, otherwise EAX = 0
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
intersect_with_corr PROC SYSCALL PUBLIC USES edi esi,
                pDestination:PRECTL

        DebugMsg <Entering MAJOR0B.intersect_with_corr,Public,KEZ>

        ddc?        ESI
        TEST        [ESI].DDC.ddc_fb,DDC_CORR_INV
        JZ        IWC_Do_correlate                ; Has corr rect in DDC
        INVOKE        recalc_correlate_rect                ; Set the corr rect
        JCXZ        IWC_Exit                        ; Null pick window

IWC_Do_correlate:
        MOV        ECX,sizeof RECTL/4
        SUB        ESP,sizeof RECTL
        MOV        EBX,ESP
        MOV        EDI,EBX
        MOV        ESI,[ESI].DDC.ddc_prddc                ; ESI --> prddc
        rddc?        ESI
        LEA        ESI,[ESI].RDDC.rddc_rcsCorr

IWC_make_rcl:                                        ; Convert rcs to a stack rcl
        LODSD
        STOSD
        LOOP        IWC_make_rcl
        MOV        ESI,EBX
        MOV        EDI,pDestination                ; EDI --> dst_rcl

;/*
;** Does our dest rect interesect with our correlation rect?
;*/

        MOV        EBX,1
        INVOKE        intersect_rcl
        ADD        ESP,sizeof RECTL

IWC_Exit:

        DebugMsg <Leaving intersect_with_corr>

        RET

intersect_with_corr ENDP

        END
