;      /*****************************************************************/
;      /*                                                               */
;      /*           Copyright (c) IBM Corporation  1987, 1992           */
;      /*                     All Rights Reserved                       */
;      /*                                                               */
;      /*****************************************************************/
;      /******************* START OF SPECIFICATIONS *********************/
;      /*                                                               */
;      /*  SOURCE FILE NAME: BUTTON.ASM                                 */
;      /*                                                               */
;      /*  DESCRIPTIVE NAME: Button handler                             */
;      /*                                                               */
;      /*  COPYRIGHT:  IBM Corp. 1992                                   */
;      /*                                                               */
;      /*  STATUS:  Version 1.0                                         */
;      /*                                                               */
;      /*  NOTES: This module contains routines to manage device        */
;      /*         buttons. The device dependent routine must call       */
;      /*         But_Engine to report the position of buttons. It      */
;      /*         is OK to call the engine multiple times with the      */
;      /*         same button state, for example, on each sample point  */
;      /*         for a barrel button.                                  */
;      /*                                                               */
;      /*         This module provides button state for the other       */
;      /*         pen driver components. Assignments are processed      */
;      /*         from the IOCTL subcomponent.                          */
;      /*                                                               */
;      /*  ENTRY POINTS:                                                */
;      /*      See public statements                                    */
;      /*  EXTERNAL REFERENCES:                                         */
;      /*      See extrn statements                                     */
;      /*                                                               */
;      /******************* END  OF  SPECIFICATIONS *********************/
.xlist
  include pensegs.inc
  include pen.inc
  include penidc.inc
  include penioctl.inc
  include penei.inc
  include struc.inc
.list

.286p

;------------------------------------------------------------------------------
; external data references
;------------------------------------------------------------------------------

extrn Device_Help  : dword

;------------------------------------------------------------------------------
; external routines
;------------------------------------------------------------------------------

extrn Idc_ReportEvent : near
extrn Dsp_GetSuppress : near

;------------------------------------------------------------------------------
; local equates
;------------------------------------------------------------------------------
FORCEGSTMODE equ -1   ; must be unique with other psba.value values

;------------------------------------------------------------------------------
; local data declarations
;------------------------------------------------------------------------------

DSEG   segment
public buttons
buttons   dw 0           ; state of buttons, 1=activated, 0=released
@dcbb     dw 0           ; pointer to button dcb

DSEG   ends


CSEG SEGMENT
     ASSUME    CS:CGROUP, SS:nothing, ES:nothing, DS:DGROUP


;---- ROUTINES TO HANDLE EVENTS -----------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; process an event for a device dependent locator device
;  dl = 0 released -1=activated
;  bx = button dcb
;  cx = button index (0 to 15)
;
; The button structure but_mask field is used by But_getButtonShift to form a
; a button mask. A Shift button will set and clear the the but_mask as the
; button is activated and released. A One Time Button will set the but_mask
; on activation, but will not clear it on release. A stroke that uses the
; shift will clear the One Time but_mask in But_GetButtonShift routine.
;------------------------------------------------------------------------------

butbit     equ word ptr bp-8
newState   equ word ptr bp-6
butEntry   equ word ptr bp-4
newButtons equ word ptr bp-2

public But_Engine
But_Engine    proc
  .if  <[bx].dcb_NumButDefs lt cx>
     stc
     ret
  .endif

  enter 8,0

  mov  ax,1   ; make a bit mask for this button
  sal  ax,cl
  mov  [butbit],ax

; calculate address of button definition

  sal  cx,BUT_DEF_SIZE_SHIFT
  mov  si,[bx].dcb_@ButDefArray
  add  si,cx

; see if state has changed
; ax = button mask for this button
; dl = new button state
; si = button entry pointer

  cmp  dl,[si].but_state
  .if  nz NEAR                   ; state change

; figure what new button mask will be

     mov  [butEntry],si
     mov  [newState],dx
     mov  cx, buttons
     or   cx,ax     ;turn it on
     .if  <zero dl>
        xor cx,ax   ;turn it off
     .endif
     mov  [newButtons], cx

; report event

     mov  di,[bx].dcb_@EiEvent   ; Addr of locator event packet
     mov  [di].bev_change,ax     ; show which changed
     mov  [di].bev_state,cx      ; show state of all buttons
     mov  ah,[si].but_value
     mov  [di].bev_value,ah      ; send value (valid for hotkeys)
     mov  al,[si].but_action
     mov  [di].bev_action,al     ; send action

     call Dsp_GetSuppress        ; get display suppress control info
                                 ; dx = cntrl info
     mov  [di].bev_cntrl,dx      ; control info

     call Idc_ReportEvent

; only process button if not suppressed

     .if  <bit [di].bev_cntrl z BEV_SUPPRESSED+BEV_BKLT_OFF>

        mov  si,[butEntry]
        mov  dx,[newState]
        mov  [si].but_state,dl  ; save new state
        mov  ax,[newButtons]
        mov  buttons,ax         ; update state of all buttons
        mov  cl,[si].but_action

; do stuff for mouse emulation
; dl = new button state
; cl = button action

        .if <cl eq SHIFTBUTTON> OR
        .if <cl eq GESTUREMODE>
           mov di,[bx].dcb_@regCaps
           mov ax,[di].bcap_typeMask
           and ax,[butbit]
           .if <zero ax>    ; its a non-barrel button
              mov dh,[si].but_flags
              .if  <nonzero dl>      ; activation
                  and dh,BUT_ONESHOT ; leave one_shot
              .else                  ; release
                 .if <bit dh z BUT_USED> ; button wasn't used, toggle one_time
                    xor dh,BUT_ONESHOT   ; toggle it
                    and dh,BUT_ONESHOT   ; only leave one_time bit
                 .else
                    xor dh,dh        ; clear all bits
                 .endif
              .endif
              mov [si].but_flags,dh
           .endif
        .endif
     .endif
  .endif
  clc
  leave
  ret
But_Engine endp

;------------------------------------------------------------------------------
; return button emulation
; returns
;  al=emulated mouse buttons
;  dx=loc_cntrl bits to be or'ed in
;
; This routine is called at the start of a stroke by the locator engine to
; latch mouse emulated buttons for the duration of the stroke. One Time shifts
; can be cleared now.
;------------------------------------------------------------------------------
public But_GetButtonShift
But_GetButtonShift proc
  push bx
  mov  bx,@dcbb
  xor  al,al            ; initialize button emulation mask to no buttons
  xor  dx,dx            ; initialize loc_cntrl to zero
  mov  si,[bx].dcb_@regCaps
  mov  cx,[si].bcap_num
  mov  si,[bx].dcb_@ButDefArray
  .repeat
     .if <bit [si].but_flags nz BUT_ONESHOT> OR
     .if <[si].but_state ne 0>
        cmp  [si].but_action, SHIFTBUTTON
        je   short gbs_10
        cmp  [si].but_action, GESTUREMODE
        jne  short gbs_19
        or  al,FORCEGSTMODE
gbs_10:
        or  al,[si].but_value
        mov [si].but_flags, BUT_USED  ; indicate used & clear oneshot
gbs_19:
     .endif
     add si, size BUT_DEF
  .loop
  .if <zero al>
     mov al,EV_BUTTON1           ; default to button 1
  .elseif <al eq FORCEGSTMODE>
     mov al,EV_BUTTON1           ; override to force gesture mode
     mov dx,LOC_GSTMODE
  .endif
  pop bx
  ret
But_GetButtonShift endp

;------------------------------------------------------------------------------
; returns
;  ax=current button state
;------------------------------------------------------------------------------
public But_GetButtons
But_GetButtons proc
  mov  ax, buttons
  ret
But_GetButtons endp

;---- MISCELLANEOUS ROUTINES --------------------------------------------------
; bx = dcb
;------------------------------------------------------------------------------
public But_CalcCaps
But_CalcCaps proc
  push bx
  mov  di,[bx].dcb_@RegCaps
  mov  [di].bcap_nullMask,0
  mov  [di].bcap_hotKeyMask,0
  mov  [di].bcap_shiftMask,0
  mov  [di].bcap_appKeyMask,0
  mov  [di].bcap_augKeyMask,0
  mov  [di].bcap_gesKeyMask,0

; set bits in caps flag words using action as an index into the caps flag
; words
; note: order of caps words MUST match action value

  mov  cx,[bx].dcb_NumButDefs
  mov  si,[bx].dcb_@ButDefArray
  lea  di,[di].bcap_nullMask
  xor  bh,bh
  mov  ax,1
  .repeat
     mov  bl, [si].but_action    ; index into masks by action
     sal  bx,1
     or   [bx+di],ax
     sal  ax,1
     add  si, size BUT_DEF
  .loop
  pop  bx
  ret
But_CalcCaps endp

CSEG ends
;---- INITIALIZATION ROUTINES -------------------------------------------------
;
; note: this code is truncated from the driver after the INIT command returns
;       to OS/2
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Initialize engine
;  bx = dcb
;------------------------------------------------------------------------------
CSEGI segment
public But_Init
But_Init proc
  mov @dcbb,bx                 ; pointer to button dcb
  ret
But_Init endp
CSEGI ends
end
