;*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 = ABS.ASM
;*
;* DESCRIPTIVE NAME = Absolute event processing routines.
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/18/92
;*
;* DESCRIPTION  Absolute event processing routines.
;*
;* FUNCTIONS Process_Absolute() Process an absolute mouse event packet.
;*           ABSProtEvent()     Process absolute event for protect mode.
;*           ABSVDMEvent()      Process absolute event for a VDM session.
;*           MapXY2RowCol()     Map an (x,y) coordinate to the current mode.
;*           CalcRelative()     Converts absolute points into a relative
;*                              motion equivalent.
;*
;* NOTES        This file contains the mouse device independent
;*              absolute event processing routines.  See the linker
;*              control file for location in link list
;*
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES   Ptr Draw DD, Device Dep DD
;*                       Update_Ptr, IntrSetup, ReportEvent.
;*
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01/18/92              DCR 1555
;*   01/18/92              60273  Fixed typo in code
;*   07/15/93  RAR2        68850  Added additional check for Xclusive Mode
;*
;*
;*
;*
;**************************************************************************


.386p

.xlist
        include mouse.inc
.list

;*
;*  External Mouse Module Data References
;*

       extrn  FgndSessn            : byte
       extrn  MEvent               : byte
       extrn  VEvent               : byte
       extrn  DeviceData           : byte
       extrn  Int_Packet           : byte
       extrn  Num_Grps             : byte

       extrn  IntEntry             : word
       extrn  VDM_Flags            : word
       extrn  VDM_Cols             : word
       extrn  VDM_Rows             : word

       extrn  MSEVDDEntry          : fword

       extrn  Calc_Num             : near
       extrn  IntrSetup            : near
       extrn  Update_Ptr           : near
       extrn  ReportProtectEvent   : near


CSEG     SEGMENT   WORD  PUBLIC  USE16 'CODE'
         ASSUME    CS:CSEG, SS:nothing, ES:nothing, DS:nothing

;*
;*   Module Procs made Public for other Mouse Modules
;*

       public  Process_Absolute
       public  MapXY2RowCol
       public  CalcRelative
       public  ABSProtEvent
       public  ABSVDMEvent
       public  Security_Hook2                ;           
       public  Security_End2                 ;           


;***********************************************************************
;*
;*  FUNCTION NAME  :  Process_Absolute
;*
;*  DESCRIPTION    :  Process an absolute mouse event packet.
;*
;*               This routine processes absolute event data from
;*               the attached pointing device.
;*
;*  INPUT          :  The packet pointed to by SInt_Packet should contain
;*                    the new absolute event. The packet format is
;*
;*                        Abs_Event    dw
;*                        Y_Pos        dw
;*                        X_Pos        dw
;*                        Y_Size       dw
;*                        X_Size       dw
;*
;*                    DS - MOUSE$ data selector
;*
;*  OUTPUT         :  None.
;*
;*  RETURN-NORMAL  :  Always.
;*
;*  RETURN-ERROR   :  Never.
;*
;*  EFFECTS        :  Pointer position updated and event saved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  Update_Ptr, CalcNewPtrPos, IntrSetup,
;*                ReportEvent.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;*     BeginSub  Process_Absolute
;*
;*      IF <fullscreen session>
;*
;*         call IntrSetup to do common event processing setup
;*         IF <session has support>
;*            call ABSProtEvent to process a fullscreen event
;*         ENDIF          /* Ignore event if no support available  */
;*
;*      ELSEIF<VMSE ready to accept events>
;*         call ABSVDMEvent to process this FS VDM event
;*      ENDIF
;*
;*      return
;*
;*     EndSub  Process_Absolute
;*
;************************************************************************

Process_Absolute  proc  near

;*
;*     First increment the entry flag for use in debugging to see if we are
;*     servicing a mouse event.  Then check if this event is for a full screen
;*     session. If it is a full screen session then call IntrSetup to setup
;*     everything needed to process a protect mode full screen mouse event.
;*     IntrSetup puts the sel:off of the mouse CB affected in DS:SI and
;*     leaves the mouse data selector in FS.  DS should be reset to
;*     the mouse data selector before exiting.
;*

Security_Hook2:                      ;           

       inc  IntEntry
       mov  al, Num_Grps             ; Get number of full screen sessions

Security_End2:                       ;           

       .if <FgndSessn lt al> AND     ; If this is a full screen session
       .if <bit VDM_Flags z VDMXMOUSEMODE> ; A windowed VDM does NOT have ;RAR2
                                           ; Exclusive mouse access!      ;RAR2

          push ds
          push fs
          call IntrSetup             ; do common event processing setup

;*
;* If carry is clear then it is OK to process the event.
;*
          .if <nc>                   ; and session has open mse support
             call ABSProtEvent       ; process a fullscreen event
          .endif
          pop  fs                    ; restore fs to entry value
          pop  ds                    ; restore our ds

       .else
          call ABSVDMEvent           ; process VDM event
       .endif

       dec  IntEntry                 ; decrement entry count

       ret                           ; return to IDC router

Process_Absolute  Endp


;******************************************************************
;*
;* FUNCTION NAME : ABSProtEvent
;*
;* DESCRIPTION   : Process absolute event for protect mode.
;*
;*  INPUT        : The packet pointed to by SInt_Packet should contain
;*                 the new absolute event. The packet format is
;*
;*                        Abs_Event    dw
;*                        Y_Pos        dw
;*                        X_Pos        dw
;*                        Y_Size       dw
;*                        X_Size       dw
;*
;*                  DS - MOUSE$ data selector
;*                  SI - pointer to the SGCB
;*
;* OUTPUT        : Absolute event processed.
;*
;* SIDE EFFECTS  : No registers preserved.
;*
;*******************************************************************
;* PSEUDOCODE    :
;*
;*           BeginSub  ABSProtEvent
;*
;*            return
;*
;*           EndSub  ABSProtEvent
;*
;***********************************************************************

ABSProtEvent  proc  near

NewRow     equ   <(word ptr [bp-4])>   ; local var for new row coord
NewCol     equ   <(word ptr [bp-6])>   ; local var for new col coord

       enter 4,0                       ; reserve space for vars

       test [SI].MType, Graphics       ; IF mode is a graphics mode
       .if  nz                         ; then
          push [si].GCol_Res           ; push the graphics resolutions
          push [si].GRow_Res           ; on stack
       .else                           ; else push the text resolutions
          push [si].TCol_Res           ; on stack
          push [si].TRow_Res           ; 
       .endif                          ; end display mode type test

       call MapXY2RowCol               ; map the absolute data.

       mov  NewRow, ax
       mov  NewCol, bx

       test [SI].D_Status, MickeyData    ; check to see if mickey data
       .if  nz                           ; to be reported.  If so

          push NewCol                    ; put new column on stack
          push NewRow                    ; and new row
          call CalcRelative              ; go calculate a relative event
          add  sp, 4                     ; clear local variables
          push 1                         ; report event no matter what.
       .else                             ; Else report type pointer pos.
          mov  ax, NewRow                ; get new row
          mov  cx, NewCol                ; get new col
          mov  fs:MEvent.Mon_Row_Pos, ax ; put in event record
          mov  fs:MEvent.Mon_Col_Pos, cx
          push 0                         ; report event if not a duplicate
       .endif                            ; Mickey Data Report Test

       push NewRow
       push NewCol
       call ReportProtectEvent              ; go report the event
       add  sp, 6

;*
;* call update_ptr to update the pointer image.  cx is the new col position
;* and dx is the new row position.  If a VDM is active the device status
;* will be set to disable calling pointer draw.

       mov  cx, NewCol
       mov  dx, NewRow
       call Update_Ptr                 ; update the pointer image

       leave
       ret                             ; return to entry routine


ABSProtEvent  endp


;*******************************************************************
;*
;* FUNCTION NAME  : ABSVDMEvent
;*
;* DESCRIPTION    : Process absolute event for a VDM session.
;*
;*  Now map the (x,y) point to the current (row,col) coordinate.
;*
;*  This is done using the following formula:
;*
;*             Row = (YPos * Row_Res) / YSize
;*
;*  Where
;*        Row is the display row
;*        YPos is the absolute y position
;*        Row_Res is the display mode row resolution
;*        YSize is the Y axis size of the absolute device.
;*
;*        The Column calculation is the same using the X
;*        and column values.
;*
;*  INPUT         : The packet pointed to by SInt_Packet should contain
;*                  the new absolute event. The packet format is
;*
;*                             Abs_Event    dw
;*                             Y_Pos        dw
;*                             X_Pos        dw
;*                             Y_Size       dw
;*                             X_Size       dw
;*
;*                       DS - MOUSE$ data selector
;*
;* OUTPUT         : Absolute event processed.
;*
;* SIDE EFFECTS   : No registers preserved.
;*
;**********************************************************************
;*  PSEUDOCODE :
;*
;*   BeginSub  ABSVDMEvent
;*
;*    Get X position
;*    Get the number of columns in the X plane
;*    Get X size
;*    Call Calc_Num the get the actual column
;*    Store new column in packet to VMSE
;*
;*    Get Y position
;*    Get the number of rows in the Y plane
;*    Get Y size
;*    Call Calc_Num the get the actual row
;*    Store new row in packet to VMSE
;*
;*    Store current SGID in packet to VMSE
;*    Store current event in packet to VMSE
;*    Turn on bit in event field indicating (ABS event)
;*
;*    IF <VMSE ready for events>
;*       Send VMSE this event
;*    ENDIF
;*
;*    return
;*
;*   EndSub  ABSVDMEvent
;*
;************************************************************************/

ABSVDMEvent  proc  near

       mov  ax, Int_Packet.X_Pos        ; get the X position
       mov  bx, VDM_Cols                ; Columns in the X plane.
       mov  cx, Int_Packet.X_Size       ; get the X size
       call Calc_Num                    ; do (ax * bx)/cx
       mov VEvent.ve_X, ax              ; New absolute col position.

       mov  ax, Int_Packet.Y_Pos        ; get the Y position
       mov  bx, VDM_Rows                ; Rows in the Y plane.
       mov  cx, Int_Packet.Y_Size       ; get the Y size
       call Calc_Num                    ; do (ax * bx)/cx
       mov VEvent.ve_Y, ax              ; New absolute row position.

;*                                                                   ;RAR2
;* If excluse mouse access mode is ON, then the VEvent.ve_SGID field ;RAR2
;* has already been updated when the VMSE called PDDCMD_XMouseMode.  ;RAR2
;*                                                                   ;RAR2
       .if <bit VDM_Flags z VDMXMOUSEMODE>                           ;RAR2
          mov  al, fgndsessn            ; Foreground FS VDM SGID
          cbw                           ; Make into a word
          mov  VEvent.ve_SGID, ax       ; Update input packet.
       .endif                                                        ;RAR2

       mov  ax, Int_Packet.Event        ; Motion/button status.
       mov  VEvent.ve_Event, ax         ; Update input packet.
       or   VEvent.ve_Event, ABSPIXEVENT; This is an ABS event.

       .if <bit VDM_Flags nz VDMREGISTERED>  ; if VDM interface enabled
          push 0                             ; push a 32 bit 1 for
          push VMSE_EVENT                    ; event notify function
          push ds                            ; selector of input packet
          push offset VEvent                 ; offset of input packet
          push 0                             ; output packet selector (N/A)
          push 0                             ; output packet offset (N/A)
          call MSEVDDEntry                   ; go notify the VDD
       .endif

       ret                                   ; return to entry routine

ABSVDMEvent  endp


;***********************************************************************
;*
;* FUNCTION NAME : MapXY2RowCol
;*
;* DESCRIPTION   : Map an (x,y) coordinate to the current mode.
;*
;* INPUT         :  stack frame  top ->  return address
;*                               row resolution
;*                               col resolution
;*
;*           SInt_Packet has the latest event data below;
;*
;*                Abs_Event    dw
;*                Y_Pos        dw
;*                X_Pos        dw
;*                Y_Size       dw
;*                X_Size       dw
;*
;*          DS - MOUSE$ data selector
;*
;* OUTPUT        : ax = new row, bx = new col
;*
;* SIDE EFFECTS  : No registers preserved.
;*
;**********************************************************************
;*
;*  PSEUDOCODE :
;*
;*             BeginSub  MapXY2RowCol
;*
;*              return
;*
;*             EndSub  MapXY2RowCol
;*
;***********************************************************************


MapXY2RowCol  Proc  Near

RowRes        equ     <(word ptr [bp+4])>
ColRes        equ     <(word ptr [bp+6])>

       ENTER 0,0

       push RowRes
       push ColRes

;*
;* Now map the (x,y) point to the current display mode space.  This is done
;* using the following formula:
;*
;*                   Row = (YPos * Row_Res) / YSize
;*
;* Where Row is the display row, YPos is the absolute y position, Col_Res
;* is the display mode row resolution and YSize is the Y axis size of
;* the absolute pointing device.  The Column calculation is the same using
;* the X and column values.
;*


       mov  ax, fs:Int_Packet.X_Pos      ; get the x position
       mov  cx, fs:Int_Packet.X_Size     ; get the x size
       pop  bx                           ; get the col resolution
       .if <cx a 0>
         call Calc_Num                  ; do (ax * bx)/cx
         dec  bx                        ; convert col resolution to 0 base
         .if <ax a bx>                  ; if new point out of range somehow
            mov  ax, bx                 ; then use the max 0 based resolution
         .endif                         ; 
         pop  bx                        ; get the row resolution
         push ax                        ; save the new point

         mov  ax, fs:Int_Packet.Y_Pos   ; get the y position
         mov  cx, fs:Int_Packet.Y_Size  ; get the y size
         .if <cx a 0>
           call Calc_Num                ; do (ax * bx)/cx
           dec  bx                      ; convert col resolution to 0 base
           .if <ax a bx>                ; if new point out of range somehow
              mov  ax, bx               ; then use the max 0 based resolution
           .endif                       ; leave new row in ax
           pop  bx
           clc                          ; indicate NO_ERROR
         .else
           pop  bx                      ; reset stack
           stc                          ; set error condition
           jmp  exit_err                ; leave
         .endif
       .else
         pop  bx                        ; reset stack
         stc                            ; set error condition
       .endif

exit_err:
       LEAVE
       ret

MapXY2RowCol  EndP


;**********************************************************************
;*
;* FUNCTION NAME : CalcRelative
;*
;* DESCRIPTION   : Converts absolute points into a relative motion
;*                 equivalent.
;*
;* INPUT         :  stack frame   top -> return address
;*                                       Row position
;*                                       Col position
;*
;* OUTPUT        : relative motion in mickeys put in the mouse event pkt
;*
;* SIDE EFFECTS  : No registers preserved.
;*
;************************************************************************
;* PSEUDOCODE    :
;*
;*               BeginSub  CalcRelative
;*
;*                return
;*
;*               EndSub  CalcRelative
;*
;************************************************************************/

CalcRelative  Proc  Near

RowPos        equ     <(word ptr [bp+4])>
ColPos        equ     <(word ptr [bp+6])>

       ENTER 0,0

       mov  ax, RowPos
       sub  ax, [si].Ptr_Row_Pos
       imul [si].Row_Cell_Size
       imul [si].RowScale_Fact
       mov  cx, 8
       idiv cx
       mov  fs:MEvent.Mon_Row_Pos, ax

;*     mov  ax, NewCol                          ;           
       mov  ax, ColPos                          ;           
       sub  ax, [si].Ptr_Col_Pos
       imul [si].Col_Cell_Size
       imul [si].ColScale_Fact
       mov  cx, 8
       idiv cx
       mov  fs:MEvent.Mon_Col_Pos, ax

       LEAVE

       ret

CalcRelative  EndP

CSEG     ENDS
         END
