Listing 2 (handler.asm)

  Comment  #

  extern void far handler(void);  /* a mouse event handler */


  Specific to mice compatible with the Microsoft Mouse Driver Interface

  External Variables:     _head,_tail: near pointers to links
            in a circular queue. Each link has the
            form mirrored by the event_q struc defined

   even                 ;use word data alignment
   event_q struc        ;mirrors EVENT Link defined in mouseq.h
   xc      dw     ?     ;x mouse coordinate
   yc      dw     ?     ;y mouse coordinate
   butstat dw     ?     ;mouse button status
   evmask  dw     ?     ;event mask ( active events at time of entry )
   vflag   dw     ?     ;"valid" flag
   nextptr dw     ?     ;pointer to next link
   event_q ends

            _head and _tail are defined in mouseq.h
            and iniitialized in the file mouseq.c,
            which is responsible for the creation and
            destruction of the queue.


  Mouse Event Handler called as a far function from the mouse driver
  when it senses an event for which the event mask has a bit set.

  Designed to be linked to a Small Memory Model C Program

  This example uses Turbo C V. 2.0

  On Entry:
     AX = bit mask for current events
      where a 1 in bit position:
         0   =   mouse cursor movement
         1   =   left button press
         2   =   right button press
         3   =   left button release
         4   =   right button release
         5 - 15: unused
     BX = button status
     CX = X mouse coordinate
     DX = Y mouse coordinate


  name     _handler

_TEXT  segment byte public 'CODE'
  assume  cs:_TEXT,ds:DGROUP
_TEXT ends
_DATA  segment word public 'DATA'
  extrn   _head:word,_tail:word

even                     ;use word data alignment
event_q struc
xc      dw     ?
yc      dw     ?
butstat dw     ?
evmask  dw     ?
vflag   dw     ?
nextptr dw     ?
event_q ends

sav_ax  dw     ?
_DATA  ends
_BSS   segment word public 'BSS'
_b@    label   byte
_BSS   ends
_TEXT   segment byte public 'CODE'

  ;Entry Point

 _handler     proc    far
  cli                    ;disable interrupts to avoid re-entry
  push   ds              ;save registers
  push   di
  mov    di,DGROUP       ;point DS to application's data segment
  mov    ds,di
  mov    sav_ax,ax       ;we're called from inside the mouse driver
           ;so keep stack pushes to a minimum

  mov    di,_tail
  mov    ax,[di].nextptr         ;get tail->next pointer
  mov    di,_head
  cmp    ax,[di]         ;if it equals head then queue is full
  jne    hndlr1
  jmp    handl_exit      ;exit if queue is full

  mov    di,_tail        ;we sacrifice one slot in queue to simplify
           ;code, similar to PC BIOS keyboard buffer

  ;store mouse event info in the queue

  mov    [di].xc,cx               ;x mouse coordinate from CX reg
  mov    [di].yc,dx               ;y mouse coordinate from DX reg
  mov    [di].butstat,bx          ;mouse button status from BX reg
  mov    ax,sav_ax                ;event mask from AX reg
  mov    [di].evmask,ax
  mov    [di].vflag, 1            ;mark queue entry "valid"
  mov    ax,[di].nextptr
  mov    _tail,ax                 ;bump tail pointer

  ;Handler Exit Point

  pop    di                       ;restore registers
  pop    ds
  sti                             ;enable interrupts
  ret                             ;far return to mouse driver
 _handler      endp
_TEXT  ends
_DATA   segment word public 'DATA'
_s@    label  byte
_DATA  ends
_TEXT  segment byte public 'CODE'
  public  _handler
_TEXT ends