home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progbas / qbnws203.arj / MOUSE.ZIP / MOUSE.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-09-03  |  54.3 KB  |  1,352 lines

  1. ;============================================================================
  2. ;   Mouse interface for QuickBASIC V4.x, Microsoft BASIC 6.X, and the
  3. ;   Microsoft BASIC Professional Development System 7.X.
  4. ;
  5. ;   Written by Tony Elliott (CIS 76220,2575)
  6. ;
  7. ;   For QBNews in March, 1991 and released into the Public Domain.
  8. ;
  9. ;   Assemble using MASM 5.1
  10. ;===========================================================================
  11.  
  12. .Model Medium, Basic
  13. .Code _MouseCode
  14.  
  15.     ; We store our variables in our code segment to keep them out of DGROUP.
  16.     
  17.     MouseButtons    db 0            ;Our "initialized" flag
  18.     PixelsOn        db 0            ;If <> 0, return coordinates in pixels
  19.     StateSegment    dw 0            ;Memory segment where mouse state is stored
  20.     SaveBytes       dw 0            ;Number of bytes required to save state
  21.     OnExitSet       db 0            ;Indicates successful call to B_OnExit
  22.  
  23.     UEventActive    db 0            ;-1 if our mouse event handler is active
  24.     EventCause      dw 0            ;The cause of the event
  25.     ButtonState     dw 0            ;When mouse event hits, button state, 
  26.     VertPos         dw 0            ; vertical and horizontal locations stored
  27.     HorizPos        dw 0            ; here until fetched by programmer.
  28.     
  29.     Extrn B$SETM    :Far            ;BASIC's SETMEM routine
  30.     Extrn SetUEvent :Far            ;Sets a BASIC flag that triggers a UEVENT.
  31.     Extrn B_OnExit  :Far            ;BASIC's routine to set procs to be called 
  32.                                     ; on program restart or termination.
  33. ;---------------------------------------------------------------------------
  34.  
  35. MousePixelsOn proc
  36.  
  37.     ;Sets an internal flag which tells us to return mouse corrdinates in
  38.     ;pixel format. The default is to return base 1 row/column coordinates
  39.     ;like BASIC uses. Use the routine MousePixelsOff to reset the
  40.     ;coordinate system back to row/columns.
  41.     
  42.     ;From BASIC:
  43.     ;
  44.     ;  DECLARE SUB MousePixelsOn ()     'This is optional
  45.     ;
  46.     ;  CALL MousePixelsOn               'Or, when the declare is present,
  47.     ;  MousePixelsOn
  48.     
  49.     mov byte ptr cs:PixelsOn, -1        ;Turn the flag on
  50.     ret                                 ;That was easy, wasn't it?
  51.     
  52. MousePixelsOn endp
  53.  
  54. ;---------------------------------------------------------------------------
  55.  
  56. MousePixelsOff proc
  57.  
  58.     ;Sets an internal flag which tells us to return mouse corrdinates in
  59.     ;base 1 row/column format. This the default. You need to call this routine
  60.     ;only if you have previously called the MousePixelsOn routine and you
  61.     ;wish to return to row/column coordinates.
  62.  
  63.     ;From BASIC:
  64.     ;
  65.     ;  DECLARE SUB MousePixelsOff ()    'This is optional
  66.     ;
  67.     ;  CALL MousePixelsOff              'Or, when the declare is present,
  68.     ;  MousePixelsOff
  69.  
  70.     mov byte ptr cs:PixelsOn,0          ;Set the flag to OFF.
  71.     ret
  72.     
  73. MousePixelsOff endp
  74.  
  75. ;---------------------------------------------------------------------------
  76.  
  77. MouseReset proc
  78.  
  79.     ; Initializes the mouse. The mouse driver is initialized to the
  80.     ; following state:
  81.     ;
  82.     ;  - Mouse pointer is at the center of the screen
  83.     ;  - Display page for mouse set to 0
  84.     ;  - Mouse pointer is hidden (off)
  85.     ;  - Mouse pointer shape is the default arrow shape in the graphics
  86.     ;    video modes or a reverse block in the text modes.
  87.     
  88.     ; From BASIC:
  89.     ;
  90.     ;  DECLARE FUNCTION MouseReset% ()
  91.     ;  
  92.     ;  NumberOfButtons% = MouseReset%
  93.     ;  IF NumberOfButtons% THEN
  94.     ;     PRINT "Mouse with";NumberOfButtons%;"buttons is installed and reset."
  95.     ;  ELSE
  96.     ;     PRINT "Mouse not detected."
  97.     ;  END IF
  98.  
  99.     xor ax,ax                           ;Function 0
  100.     int 33h                             ;Returns number of buttons in bx
  101.     or bx,bx                            ;Is bx non-zero?
  102.     jz @F                               ;No. Mouse not detected. Get out.
  103.     
  104.     mov cs:MouseButtons,bl              ;Mouse was detected. Store # buttons.
  105.  
  106.     push cs                             ;Setup for call to B_OnExit. Push
  107.     mov cx,offset MouseExit             ; segment and offset of our clean-
  108.     push cx                             ; up routine onto the stack.
  109.     call B_OnExit                       ;Tell BASIC to stick it (in its table)
  110.  
  111.     mov al,cs:MouseButtons              ;Move # of buttons into ax for return
  112.     xor ah,ah                           ;Zero ah
  113.     
  114. @@: ret                                 ;Back to BASIC. Contents of AX is
  115.                                         ;returned as function result.
  116. MouseReset endp
  117.  
  118. ;-----------------------------------------------------------------------------
  119.  
  120. MouseAlreadyReset proc
  121.  
  122.     ;Returns the number of button the mouse has -if- the driver has already
  123.     ;been reset, otherwise it returns zero. This routine provides an easy
  124.     ;method of determining if the mouse driver has already been reset by the
  125.     ;current program.
  126.  
  127.     ;From BASIC:
  128.     ;
  129.     ;DECLARE FUNCTION MouseAlreadyReset% ()
  130.     ;Buttons% = MouseAlreadyReset%
  131.     ;IF Buttons% THEN
  132.     ;   PRINT "Mouse with";Buttons%;" buttons has already been reset!"
  133.     ;ELSE
  134.     ;   PRINT "Mouse has not yet been reset."
  135.     ;END IF
  136.  
  137.     xor ah,ah                       ;Zero AH
  138.     mov al,cs:MouseButtons          ;Number of buttons into al
  139.     ret                             ;Returns AX as result of integer function
  140.  
  141. MouseAlreadyReset endp
  142.  
  143. ;-----------------------------------------------------------------------------
  144.  
  145. MouseInstalled proc uses ds
  146.     
  147.     ;Check to see if a mouse is installed WITHOUT resetting it. The
  148.     ;MouseReset function will still have to be invoked before the other
  149.     ;mouse routines will function.
  150.  
  151.     ;From BASIC:
  152.     ;
  153.     ;  DECLARE FUNCTION MouseInstalled% ()
  154.     ;
  155.     ;  IF MouseInstalled% THEN
  156.     ;     PRINT "A mouse IS installed."
  157.     ;  ELSE
  158.     ;     PRINT "A mouse was not detected."
  159.     ;  END IF
  160.         
  161.     cmp cs:MouseButtons,0               ;Have we already initialized it?
  162.     jz @F                               ;If not, continue the check.
  163.     
  164.     mov ax,-1                           ;It has been reset so it must be
  165.     jmp short ExitInstall               ;installed. Set return to -1 (TRUE).
  166.     
  167. @@:
  168.     xor ax,ax                           ;Zero ax
  169.     assume ds:nothing
  170.     mov ds,ax                           ;Move that into ds referencing the IVT
  171.     mov bx,ds:[0cch]                    ;Offset of Int 33h (mouse) into bx
  172.     mov cx,ds:[0ceh]                    ;Segment of Int 33h into cx
  173.     or cx,cx                            ;Is segment zero?
  174.     jz ExitInstall                      ;If so, exit
  175.     mov ds,cx                           ;Point ds to segment of Int 33h handler
  176.     cmp byte ptr ds:[bx],0cfh           ;Is the handler pointing to an IRET?
  177.     jz ExitInstall                      ;If so, no mouse driver loaded. Exit.
  178.     not ax                              ;If it's not an IRET then it must be
  179.                                         ; a valid driver. Return -1 (TRUE).
  180. ExitInstall:
  181.     ret                                 ;Back to BASIC.
  182.     
  183. MouseInstalled endp
  184.  
  185. ;------------------------------------------------------------------------------
  186.  
  187. MousePointerOn proc
  188.  
  189.     ;Displays the mouse pointer (cursor) and cancels any previous mouse
  190.     ;exclusion area defined with the routine MouseSetExclusionArea.
  191.  
  192.     ;Note: Each time this routine is called, the mouse driver increments an
  193.     ;      internal counter. The MousePointerOff routine decrements the
  194.     ;      counter. The MouseReset routine set the counter to an initial
  195.     ;      value of -1. While the counter < 0 the mouse pointer will be
  196.     ;      hidden and when the counter >= 0 the pointer is visible.
  197.     ;      In other words, if MousePointerOff was called three
  198.     ;      successive times, MousePointerOn would have to be called three
  199.     ;      times before the pointer would be physically turned back on.
  200.     
  201.     ;From BASIC:
  202.     ;
  203.     ;  DECLARE SUB MousePointerOn ()    'This is optional.
  204.     ;
  205.     ;  CALL MousePointerOn              'Or, if you used the DECLARE, simply
  206.     ;  MousePointerOn
  207.     
  208.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  209.     jz @F                               ;If not, exit.
  210.     
  211.     mov ax,1                            ;Function 1 - Show pointer
  212.     int 33h                             ;Call the mouse driver.
  213.     
  214. @@: ret                                 ;Back to BASIC.
  215.     
  216. MousePointerOn endp
  217.  
  218. ;-----------------------------------------------------------------------------
  219.  
  220. MousePointerOff proc
  221.  
  222.     ;This routine makes the mouse pointer visible. Please see the special
  223.     ;note under the MousePointerOn routine for details about the mouse
  224.     ;driver's internal counter.
  225.     
  226.     ;Note: Even though the mouse pointer is not visible, the driver
  227.     ;      continues to track the mouse pointer position.
  228.     
  229.     ;From BASIC:
  230.     ;
  231.     ;  DECLARE SUB MousePointerOff ()   'This is optional.
  232.     ;
  233.     ;  CALL MousePointerOff             'Or, if you used the DECLARE, simply
  234.     ;  MousePointerOff
  235.     
  236.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  237.     jz @F                               ;If not, exit.
  238.     
  239.     mov ax,2                            ;Function 2 - Show mouse pointer
  240.     int 33h                             ;Call the mouse driver.
  241.     
  242. @@: ret                                 ;Back to BASIC
  243.     
  244. MousePointerOff endp
  245.  
  246. ;-----------------------------------------------------------------------------
  247.  
  248. MouseGetStatus proc, Lb:word, Rb:Word, Cb:Word, Row:Word, Column:Word
  249.  
  250.     ;Returns the current "real time" state of the mouse buttons and the
  251.     ;mouse pointers current position in row/column coordinates. A value
  252.     ;of -1 (TRUE) returned for Lb%, Rb% or Cb% indicates that the
  253.     ;respective button is currently pressed and a value of zero (FALSE)
  254.     ;indicates the button is not pressed.
  255.     
  256.     ;From BASIC:
  257.     ;
  258.     ;   DECLARE SUB MouseGetStatus(Lb%, Rb%, Cb%, Row%, Column%)    'Optional
  259.     ;
  260.     ;   CALL MouseGetStatus(Lb%, Rb%, Cb%, Row%, Column%)           'Or
  261.     ;   MouseGetStatus Lb%, Rb%, Cb%, Row%, Column%
  262.  
  263.     xor ax,ax                           ;Assume all buttons off
  264.     mov bx,ax
  265.     mov cx,ax                           ;Row/Column 0
  266.     mov dx,ax
  267.     
  268.     cmp cs:MouseButtons,0               ;Mouse initialized?
  269.     jz @F                               ;If not, exit.
  270.     
  271.     mov ax,3                            ;Function 3 - Get status
  272.     int 33h                             ;Call the mouse driver
  273.     
  274.     call _CommonFromPixels
  275.  
  276. @@:
  277.     call _SetupReturn
  278.     ret                                 ;Back to BASIC
  279.     
  280. MouseGetStatus endp
  281.     
  282. ;-----------------------------------------------------------------------------
  283.  
  284. MouseSetPointer proc, Row:Word, Column:Word
  285.  
  286.     ; Set the mouse pointer position. The format for the coordinates is
  287.     ; based on the most recent call to either of MousePixelsOn or
  288.     ; MousePixelsOff. If neither have been previously called, row/column
  289.     ; coordinates is the default.
  290.     
  291.     ; If coordinates provided are outside the physical screen or outside of
  292.     ; the vertical or horizontal limits set by the MouseSetWindow routine,
  293.     ; the coordinates are adjusted automatically.
  294.     
  295.     ; From BASIC:
  296.     ;
  297.     ;   DECLARE SUB MouseSetPointer(Row%, Column%)   'Optional
  298.     ;
  299.     ;   CALL MouseSetPointer(Row%, Column%)          'Or, if using the declare,
  300.     ;   MouseSetPointer Row%, Column%
  301.     
  302.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  303.     jz @F                               ;If not, exit.
  304.  
  305.     assume ds:dgroup    
  306.     mov bx,[Row]                        ;Pointer to Row (Vertical) into bx
  307.     mov dx,[bx]                         ;Row% into dx
  308.     mov bx,[Column]                     ;Pointer to Column into bx
  309.     mov cx,[bx]                         ;Column% into cx
  310.     
  311.     call _CommonToPixels                ;Convert to pixels, if necessary
  312.     
  313.     mov ax,4                            ;Mouse function 4 - Set position
  314.     int 33h                             ;Call the mouse driver
  315.     
  316. @@: ret                                 ;Back to BASIC.
  317.  
  318. MouseSetPointer endp
  319.  
  320. ;-----------------------------------------------------------------------------
  321.  
  322. MousePressInfo proc, Button:Word, Row:Word, Column:Word
  323.  
  324.     ; Returns the number of times the specified mouse button has been
  325.     ; pressed since the last time this routine was called. It also returns
  326.     ; the position where the specified button was pressed.
  327.     
  328.     ; From BASIC:
  329.     ;
  330.     ;   DECLARE FUNCTION MousePressInfo% (Button%, Row%, Column%)
  331.     ;
  332.     ;   NumberOfPresses% = MousePressInfo%(Button%,Row%,Column%)
  333.     ;
  334.     ; On entry, Button% = 0 for the left button
  335.     ;                     1 for the right button
  336.     ;                     2 for the center button (if any)
  337.     ;
  338.     ; On exit, the result of the function indicates the number of times
  339.     ; the specified button has been pressed since this routine was last
  340.     ; called. Row% and Column% will contain the coordinates where the
  341.     ; specified button was last pressed. The current coordinate system
  342.     ; is used (See MousePixelsOn and MousePixelsOff).
  343.     
  344.     ;This block of code is used by the MousePressInfo and the MouseReleaseInfo
  345.     ;routines. BX contains the function number (5 for PressInfo or 6 for
  346.     ;release info). The common entry point is CommonButtonInfo.
  347.  
  348.     mov bx,5                            ;Function 5 - Get pressed info
  349.  
  350. CommonButtonInfo::                      ;Both colons are supposed to be there
  351.     xor ax,ax                           ;Zero our return registers in case
  352.     mov cx,ax                           ;mouse has not been initialized. This
  353.     mov dx,ax                           ;way, we'll return all zeros.
  354.     
  355.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  356.     jz @F                               ;If not, exit
  357.  
  358.     mov ax,bx                           ;Put function number into ax
  359.     
  360.     mov bx,[Button]                     ;Pointer to Button% into bx
  361.     mov bx,[bx]                         ;Button% value into bx
  362.     
  363.     int 33h                             ;Call the mouse driver
  364.     
  365.     push bx                             ;Save bx
  366.     call _CommonFromPixels              ;Convert pixels to row/columns, if needed
  367.     pop ax
  368.     
  369. @@:
  370.     mov bx,[Row]                        ;Pointer to Row% into bx
  371.     mov [bx],dx                         ;Vertical position into Row%
  372.     mov bx,[Column]                     ;Pointer to Column% into bx
  373.     mov [bx],cx                         ;Horizontal position into Column%
  374.     ret                                 ;Number of presses in ax returned as
  375.                                         ; result of function.
  376. MousePressInfo endp
  377.  
  378. ;-----------------------------------------------------------------------------
  379.  
  380. MouseReleaseInfo proc, Button:Word, Row:Word, Column:Word
  381.  
  382.     ; Returns the number of times the specified mouse button has been
  383.     ; released since the last time this routine was called. It also returns
  384.     ; the position where the specified button was last released.
  385.     
  386.     ; From BASIC:
  387.     ;
  388.     ;   DECLARE FUNCTION MouseReleaseInfo% (Button%, Row%, Column%)
  389.     ;
  390.     ;   NumberOfReleases% = MouseReleaseInfo%(Button%,Row%,Column%)
  391.     ;
  392.     ; On entry, Button% = 0 for the left button
  393.     ;                     1 for the right button
  394.     ;                     2 for the center button (if any)
  395.     ;
  396.     ; On exit, the result of the function indicates the number of times
  397.     ; the specified button has been released since this routine was last
  398.     ; called. Row% and Column% will contain the coordinates where the
  399.     ; specified button was last released. The current coordinate system
  400.     ; is used (See MousePixelsOn and MousePixelsOff).
  401.     
  402.     mov bx,6                            ;Function 6 - Get Release info
  403.     jmp short CommonButtonInfo
  404.     
  405. MouseReleaseInfo endp
  406.  
  407. ;-----------------------------------------------------------------------------
  408.  
  409. MouseSetWindow proc,TopRow:Word,LeftColumn:Word,BottomRow:Word,RightColumn:Word
  410.  
  411.     ; Set the coordinates for a window in which the mouse pointer is allowed
  412.     ; to move. By default, the pointer is allowed to move freely over the
  413.     ; entire screen. This routine allows you to limit the mouse pointer's
  414.     ; movement to a specific rectangular area of the screen.
  415.     
  416.     ; From BASIC:
  417.     ;
  418.     ;   DECLARE SUB MouseSetWindow(TopRow%, LeftColumn%, BottomRow%,_
  419.     ;                              RightColumn%)
  420.     ;
  421.     ;   CALL MouseSetWindow(10, 10, 20, 70)
  422.     
  423.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  424.     jz @F                               ;If not, exit
  425.     
  426.     mov bx,[BottomRow]                  ;Pointer to BottomRow% into bx
  427.     mov dx,[bx]                         ;BottomRow% into dx
  428.     mov bx,[RightColumn]                ;Pointer to RightColumn% into bx
  429.     mov cx,[bx]                         ;RightColumn% into cx
  430.     call _CommonToPixels                ;Convert to pixels, if needed
  431.     push dx                             ;Save BottomRow and RightColumn
  432.     push cx                             ; on stack until needed later.
  433.     
  434.     mov bx,[TopRow]                     ;Pointer to TopRow% into bx
  435.     mov dx,[bx]                         ;TopRow% into dx
  436.     mov bx,[LeftColumn]                 ;Pointer to LeftColumn% into bx
  437.     mov cx,[bx]                         ;LeftColumn% into cx
  438.     call _CommonToPixels                ;Convert to pixels, if needed
  439.         
  440.     mov bx,dx                           ;Hold TopRow in bx for now
  441.     pop dx                              ;RightColumn coordinate into dx
  442.     
  443.     mov ax,7                            ;Function 7 - Set horizontal limits
  444.     int 33h                             ;Call mouse driver
  445.     
  446.     mov cx,bx                           ;TopRow into cx
  447.     pop dx                              ;BottomRow into dx
  448.  
  449.     mov ax,8                            ;Function 8 - Set vertical limits
  450.     int 33h                             ;Call mouse driver
  451.  
  452. @@: ret    
  453.  
  454. MouseSetWindow endp
  455.  
  456. ;-----------------------------------------------------------------------------
  457.  
  458. MouseSetHardwarePointer proc uses si, StartScan:Word, EndScan:Word
  459.  
  460.     ; Defines the shape and characteristics of the mouse pointer used in
  461.     ; text video modes. The "hardware" cursor is simply a character block
  462.     ; which the programmer can control the starting scan line
  463.     ; and the ending scan line (i.e., the size and shape of the
  464.     ; block). When the hardware cursor is moved over the screen, it appears 
  465.     ; as a blinking block.
  466.     
  467.     ;From BASIC:
  468.     ;
  469.     ;   DECLARE SUB MouseSetHardwarePointer(StartScan%, EndScan%)
  470.     ;
  471.     ;   CALL MouseSetHardwarePointer(0, 7)
  472.     
  473.     mov bx,1                            ;Set hardware cursor
  474.     
  475.     ; The following code is shared between MouseSetHardwarePointer and
  476.     ; MouseSetSoftwarePointer.
  477.     
  478. CommonSetCursor::                       ;Both colons are supposed to be there
  479.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  480.     jz @F                               ;If not, exit.
  481.     
  482.     mov ax,0ah                          ;Function 0Ah - Set pointer attributes
  483.     mov si,[StartScan]                  ;Offset of Param1 into si
  484.     mov cx,[si]                         ;Param1 into cx (StartScan or AND mask)
  485.     mov si,[EndScan]                    ;Offset of Param1 into si
  486.     mov dx,[si]                         ;Param2 into dx (EndScan or XOR mask)
  487.     int 33h                             ;Call mouse driver
  488.     
  489. @@: ret
  490.     
  491. MouseSetHardwarePointer endp
  492.         
  493. ;-----------------------------------------------------------------------------
  494.  
  495. MouseSetSoftwarePointer proc uses si, AndMask:Word, XorMask:Word
  496.  
  497.     ; Sets characteristics of mouse "software" pointer. This type of pointer
  498.     ; is used only in text modes and physically manipulates whatever character
  499.     ; and attribute that is under it. The values passed in Param1 (AND mask)
  500.     ; and in Param2 (XOR mask) determine exactly how the character and
  501.     ; attribute will be manipulated.
  502.  
  503.     ;From BASIC:
  504.     ;
  505.     ;   DECLARE SUB MouseSetSoftwarePointer (AndMask%, XorMask%)
  506.     ;
  507.     ;   CALL MouseSetSoftwarePointer(&H77ff, &H7700)
  508.     
  509.     ; The AND mask determines what part of the character/attribute pair
  510.     ; will be passed through and the XOR mask determines which of the
  511.     ; resulting bits will be toggled. In each case, the low byte of the
  512.     ; integer applies to the character and the high bytes applies to the
  513.     ; attribute.
  514.     
  515.     mov bx, 0
  516.     jmp short CommonSetCursor
  517.     
  518. MouseSetSoftwarePointer endp
  519.  
  520. ;-----------------------------------------------------------------------------
  521.  
  522. MouseMovement proc, Rows:Word, Columns:Word
  523.  
  524.     ; Returns the net mouse displacement since the last call to this routine.
  525.     ; In other words, it tells you how many "mickeys" (approx 1/200th of an
  526.     ; inch) the mouse has moved from it's position the last time this routine
  527.     ; was called.
  528.     
  529.     ; From BASIC:
  530.     ;
  531.     ;   DECLARE SUB MouseMovement (Rows%, Columns%)
  532.     ;
  533.     ;   CALL MouseMovement (Rows%, Columns%)
  534.  
  535.     xor cx,cx                           ;Zero cx and dx so zeros will be
  536.     mov dx,cx                           ;returned if mouse not initialized
  537.  
  538.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  539.     jz @F                               ;If not, exit.
  540.     
  541.     mov ax,0bh                          ;Function 0Bh - Read movement counters
  542.     int 33h                             ;Call mouse driver
  543.     
  544. @@:
  545.     mov bx,[Rows]                       ;Pointer to Rows% into bx
  546.     mov [bx],dx                         ;Vertical movement into Rows%
  547.     mov bx,[Columns]                    ;Pointer to Columns into bx
  548.     mov [bx],cx                         ;Horizontal movement into Columns%
  549.     ret                                 ;Back to BASIC.
  550.     
  551. MouseMovement endp
  552.  
  553. ;-----------------------------------------------------------------------------
  554.  
  555. MouseSetRatio proc, VertRatio:word, HorizRatio:Word
  556.  
  557.     ; Sets the ratio between the amount mouse physical mouse movement
  558.     ; (mickeys) and the amount of movement reflect by the mouse pointer
  559.     ; on the screen. The value passed in reflects the number of mickeys
  560.     ; required to move the pointer 8 pixels. The default is 8 mickeys per
  561.     ; 8 pixels (1 mickey per pixel) horizontal and 16 mickeys per 8 pixels
  562.     ; (2 mickeys per pixel) of vertical movement. A value between
  563.     ; 1 and 32767 mickeys can be specified.
  564.     
  565.     ;From BASIC:
  566.     ;
  567.     ;   DECLARE SUB MouseSetRatio (VertRatio%, HorizRatio%) 'Optional
  568.     ;
  569.     ;   CALL MouseSetRatio(8, 4)        'Doubles mouse sensitivity
  570.     
  571.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  572.     jz @F                               ;If not, exit.
  573.  
  574.     mov bx,[VertRatio]                  ;Pointer to VertRatio% into bx
  575.     mov dx,[bx]                         ;VertRatio% into dx
  576.     mov bx,[HorizRatio]                 ;Pointer to HorizRatio% into bx
  577.     mov cx,[bx]                         ;HorizRatio% into cx
  578.     
  579.     mov ax,0fh                          ;Function 0Fh - Set mickey/pixel ratio
  580.     int 33h                             ;Call mouse driver
  581.     
  582. @@: ret                                 ;Back to BASIC
  583.     
  584. MouseSetRatio endp
  585.  
  586. ;-----------------------------------------------------------------------------
  587.  
  588. MouseSetExclusionArea proc uses si di, TopRow:Word, LeftColumn:Word, BottomRow:Word, RightColumn:Word
  589.  
  590.     ; If the mouse pointer is moved into the rectangular area of the screen
  591.     ; defined by this routine, the mouse pointer will be turned off.
  592.     
  593.     ;From BASIC:
  594.     ;
  595.     ;   DECLARE SUB MouseSetExclusionArea (TopRow%, LeftColumn%, BottomRow%,_
  596.     ;                                      RightColumn%)
  597.     ;
  598.     ;   CALL MouseSetExclusionArea (1, 1, 3, 80)
  599.     
  600.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  601.     jz @F                               ;If not, exit.
  602.     
  603.     mov bx,[BottomRow]
  604.     mov dx,[bx]                         ;BottomRow% into dx
  605.     mov bx,[RightColumn]
  606.     mov cx,[bx]                         ;RightColumn into cx
  607.     
  608.     call _CommonToPixels                ;Convert to pixels, if needed.
  609.     
  610.     mov si,cx                           ;Move bottom/right coordinates into
  611.     mov di,dx                           ; si and di.
  612.     
  613.     mov bx,[TopRow]
  614.     mov dx,[bx]                         ;TopRow% into dx
  615.     mov bx,[LeftColumn]
  616.     mov cx,[bx]                         ;LeftColumn% into cx
  617.     
  618.     call _CommonToPixels                ;Convert to pixels, if needed
  619.     
  620.     mov ax,10h                          ;Function 10h - Set exclusion area
  621.     int 33h                             ;Call mouse driver.
  622.     
  623. @@: ret                                 ;Back to BASIC.
  624.     
  625. MouseSetExclusionArea endp
  626.  
  627. ;-----------------------------------------------------------------------------
  628.  
  629. MouseSetDblSpd proc, MickeysPerSecond:Word
  630.  
  631.     ; Sets the mouse pointer "double speed threshold". If the mouse is moved
  632.     ; faster than the specified number of MickeysPerSecond, the mouse pointer
  633.     ; will kick into overdrive and effectively move twice as fast. The
  634.     ; default is 64 Mickeys (approx 1/3 inch) per second.
  635.  
  636.     ; Passing a large value (such as 10,000) effectively disables the
  637.     ; speed doubling effect.
  638.     
  639.     ;From BASIC:
  640.     ;
  641.     ;   DECLARE SUB MouseSetDblSpeed (MickeysPerSecond%)
  642.     ;
  643.     ;   CALL MouseSetDblSpeed(200)          'Set it to 1 inch per second
  644.     
  645.     cmp cs:MouseButtons,0                   ;Has mouse been initialized?
  646.     jz @F                                   ;If not, exit.
  647.     
  648.     mov bx,[MickeysPerSecond]
  649.     mov dx,[bx]                             ;MickeysPerSecond% into dx
  650.     
  651.     mov ax,13h                              ;Function 13h - Set double speed threshold
  652.     int 33h                                 ;Call the mouse driver
  653.     
  654. @@: ret                                     ;Back to BASIC
  655.     
  656. MouseSetDblSpd endp    
  657. ;-----------------------------------------------------------------------------
  658.  
  659. MouseWaitForRelease proc
  660.  
  661.     ; Waits for all mouse buttons to be released before returning control
  662.     ; to the calling program.
  663.     
  664.     ;From BASIC:
  665.     ;
  666.     ;   DECLARE SUB MouseWaitForRelease ()      'Optional
  667.     ;
  668.     ;   CALL MouseWaitForRelease                'Or, if declare is present,
  669.     ;   MouseWaitForRelease
  670.     
  671.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  672.     jz WaitReleaseExit                  ;If not, exit.
  673.     
  674. @@:
  675.     mov ax,3                            ;Function 3 - Get mouse status
  676.     int 33h                             ;Call Mouse driver.
  677.     test bl,7                           ;Are bit 0, 1 and 2 all off?
  678.     jnz @B                              ;If not, loop until they are.
  679.     
  680. WaitReleaseExit:
  681.     ret                                 ;Back to BASIC.
  682.     
  683. MouseWaitForRelease endp
  684.  
  685. ;-----------------------------------------------------------------------------
  686. MouseSaveState proc
  687.  
  688.     ; Save the current mouse state including, position, visibility, and
  689.     ; other characteristics. You could use this routine prior to SHELLing
  690.     ; another program which could use the mouse.
  691.     
  692.     ; The MouseRestoreState routine restores the previous state of the mouse.
  693.     
  694.     ; This routine make a call to BASIC's SETMEM code to release enough
  695.     ; memory to DOS to save the mouse state. When the MouseRestoreState
  696.     ; routine is CALLed, the memory is released from DOS and given back
  697.     ; to BASIC.
  698.     
  699.     ; Note: This routine can be DECLAREd as a SUB or a FUNCTION. If declared
  700.     ;       as an integer FUNCTION, -1 (TRUE) is returned if the state was
  701.     ;       saved successfully and 0 (FALSE) if unsuccessful (due to
  702.     ;       insufficient memory). If you don't care about the success or
  703.     ;       failure of the operation, you can simply DECLARE it as a SUB
  704.     ;       without parameters.
  705.     ;
  706.     ;From BASIC:
  707.     ;
  708.     ;   DECLARE SUB MouseSaveState ()
  709.     ;   CALL MouseSaveState
  710.  
  711.     ;      -or-
  712.  
  713.     ;   DECLARE FUNCTION MouseSaveState% ()
  714.     ;   IF MouseSaveState% THEN
  715.     ;       PRINT "Mouse state saved successfully"
  716.     ;   ELSE
  717.     ;       PRINT "Insufficient memory to save mouse state!"
  718.     ;   END IF
  719.     
  720.     cmp cs:MouseButtons,0               ;Has mouse been initialized?
  721.     jz SaveStateExit                    ;If not, exit
  722.  
  723.     cmp cs:StateSegment,0               ;Do we already have a state saved?
  724.     jz @F                               ;If not, continue
  725.     call far ptr MouseRestoreState      ;If we do, release it.
  726.     
  727. @@:
  728.     mov ax,15h                          ;Function 15h - Mouse save buffer size
  729.     int 33h                             ;Call mouse driver
  730.     
  731.     add bx,32                           ;Add two paragraphs (because of SETMEM)
  732.     mov cs:SaveBytes,bx                 ;Save for later
  733.     neg bx                              ;Make negative (SETMEM releases mem)
  734.     mov dx,-1                           ;Extend the negative sign into MSW
  735.     push dx                             ;Push long int on stack
  736.     push bx
  737.     call B$SetM                         ;Do the SETMEM
  738.     
  739.     mov bx,cs:SaveBytes                 ;Restore number of bytes
  740.     mov cl,4                            ;Divide by 16 (Dos wants paragraphs)
  741.     shr bx,cl                           ;Much faster than DIViding
  742.     mov ax,4800h                        ;Dos allocate memory function
  743.     int 21h                             ;Call DOS
  744.     jc AllocError                       ;Whoops - not enough memory
  745.     
  746.     mov cs:StateSegment,ax              ;Store it here
  747.     xor dx,dx                           ;Offset of buffer area
  748.     mov es,ax                           ;Segment of buffer goes here
  749.     mov ax,16h                          ;Function 16h - Save mouse state
  750.     int 33h                             ;Call mouse driver
  751.     mov ax,-1                           ;If declared as function, return TRUE
  752.     
  753. SaveStateExit:
  754.     ret                                 ;Back to BASIC
  755.     
  756. AllocError:
  757.     xor ax,ax                           ;Zero ax so a FALSE result will be
  758.     jmp short SaveStateExit             ; returned if declared as function.
  759.     
  760. MouseSaveState endp
  761.  
  762. ;-----------------------------------------------------------------------------
  763.  
  764. MouseRestoreState proc
  765.  
  766.     ; Restores the state of the mouse if previously saved with the
  767.     ; MouseSaveState routine. See the MouseSaveState routine for additonal
  768.     ; usage notes.
  769.     
  770.     ;From BASIC:
  771.     ;
  772.     ;   DECLARE SUB MouseRestoreState ()        'Optional
  773.     ;   CALL MouseRestoreState                  'Or, if declare is present,
  774.     ;   MouseRestoreState
  775.     
  776.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  777.     jz @F                               ;If not, exit
  778.     
  779.     cmp cs:StateSegment,0               ;Has a state been saved?
  780.     jz @F                               ;If not, exit
  781.  
  782.     mov ax,2                            ;The restore function doesn't turn off
  783.     int 33h                             ;current cursor, so we'll do it.
  784.                                             
  785.     mov es,cs:StateSegment              ;Segment of buffer into es
  786.     xor dx,dx                           ;Offset of buffer is zero.
  787.     mov ax,17h                          ;Function 17h - Restore mouse state
  788.     int 33h                             ;Call mouse driver
  789.     
  790.     mov ax,4900h                        ;Dos function 49h - Free memory block
  791.     int 21h                             ;Call Dos
  792.     
  793.     mov ax,cs:SaveBytes                 ;Number of bytes BASIC gave to us
  794.     xor dx,dx                           ;Zero dx
  795.     push dx                             ;Push long int onto stack for SETMEM
  796.     push ax
  797.     call B$SetM                         ;Give the buffer space back to BASIC
  798.     
  799.     mov cs:StateSegment,0               ;Zero our variable
  800.     
  801. @@: ret                                 ;Back to BASIC
  802.  
  803. MouseRestoreState endp
  804.  
  805. ;-----------------------------------------------------------------------------
  806.  
  807. MouseGetSensitivity proc uses si, VertRatio:Word, HorizRatio:Word, DblSpd:Word
  808.  
  809.     ; Returns the current mouse "sensitivity" related settings. See the
  810.     ; routines MouseSetRatio and MouseSetDblSpd for more information
  811.     
  812.     ;From BASIC:
  813.     ;
  814.     ;   DECLARE SUB MouseGetSensitivity (VertRatio%, HorizRatio%, DblSpd%)
  815.     ;   CALL MouseGetSensitivity (VertRatio%, HorizRatio%, DblSpd%)
  816.  
  817.     xor bx,bx                           ;Zero these registers. If mouse not
  818.     mov cx,bx                           ; initialized, all parameters will be
  819.     mov dx,bx                           ; returned with zero values.
  820.     
  821.     cmp cs:MouseButtons,0               ;Has mouse been initialized?
  822.     jz @F                               ;If not, exit
  823.     
  824.     mov ax,1bh                          ;Function 1Bh - Get mouse sensitivity
  825.     int 33h                             ;Call mouse driver
  826.     
  827. @@:
  828.     mov si,[VertRatio]
  829.     mov [si],cx                         ;Move data in cx to VertRatio%
  830.     mov si,[HorizRatio]
  831.     mov [si],bx                         ;Data in bx to HorizRatio%
  832.     mov si,[DblSpd]
  833.     mov [si],dx                         ;Double-speed ratio into DblSpd%
  834.     ret
  835.  
  836. MouseGetSensitivity endp
  837.  
  838. ;-----------------------------------------------------------------------------
  839.  
  840. MouseGetPage proc
  841.  
  842.     ; Returns the display page the mouse pointer is currently visible on. See
  843.     ; MouseSetPage to change the pointer's current display page. Returns -1
  844.     ; if the mouse has not yet been initialized.
  845.  
  846.     ;From BASIC:
  847.     ;
  848.     ;   DECLARE FUNCTION MouseGetPage% ()
  849.     ;
  850.     ;   PRINT "The current pointer display page is"; MouseGetPage%
  851.     
  852.     mov bx, -1                          ;Assume NOT initialized
  853.     
  854.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  855.     jz @F                               ;If not, exit
  856.     
  857.     mov ax,1eh                          ;Function 1Eh - Get pointer page
  858.     int 33h                             ;Call the mouse driver
  859.     
  860. @@:
  861.     mov ax,bx                           ;Put result in ax for return
  862.     ret                                 ;Back to BASIC.
  863.     
  864. MouseGetPage endp
  865.  
  866. ;-----------------------------------------------------------------------------
  867.  
  868. MouseSetPage proc, PointerPage:Word
  869.  
  870.     ; Sets the current mouse pointer display page. Be sure that your current
  871.     ; video mode supports the specified page number. See BASIC's SCREEN
  872.     ; statement documention for more info.
  873.     
  874.     ;From BASIC:
  875.     ;
  876.     ;   DECLARE SUB MouseSetPage(PointerPage%)  'Optional
  877.     ;   CALL MouseSetPage(1)                    'Or, if the declare is present,
  878.     ;   MouseSetPage 1
  879.  
  880.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  881.     jz @F                               ;If not, exit
  882.     
  883.     mov bx,[PointerPage]
  884.     mov bx,[bx]                         ;Put Page% into bx
  885.     
  886.     mov ax,1dh                          ;Function 1Dh - Select pointer page
  887.     int 33h                             ;Call mouse driver
  888.     
  889. @@: ret                                 ;Back to BASIC
  890.     
  891. MouseSetPage endp
  892.  
  893. ;-----------------------------------------------------------------------------
  894.  
  895. MouseGetInfo proc uses si, MajorV:word, MinorV:Word, MouseType:Word, Irq:Word
  896.  
  897.     ; Returns information about the current mouse hardware and software:
  898.     
  899.     ; MajorVer% - The Major mouse driver version (7 for 7.04). It is returned
  900.     ;             as zero if the mouse has not been initialized.
  901.  
  902.     ; MinorVer% - The Minor mouse driver version (4 for 7.04)
  903.  
  904.     ; MouseType% - 1 = bus mouse, 2 = serial mouse, 3 = InPort mouse,
  905.     ;              4 = PS/2 mouse, 5 = HP mouse
  906.  
  907.     ; Irq% - The hardware Irq line that the mouse driver is using. 0 = PS/2,
  908.     ;        or 2, 3, 4, 5, or 7 for all others.
  909.     
  910.     ;From BASIC:
  911.     ;
  912.     ;   DECLARE SUB MouseGetInfo(MajorV%, MinorV%, MouseType%, Irq%)
  913.     ;   CALL MouseGetInfo(MajorV%, MinorV%, MouseType%, Irq%)
  914.     
  915.     xor bx,bx                           ;Zero registers so results will be 
  916.     mov cx,bx                           ;returned as zero if not initialized.
  917.     
  918.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  919.     jz @F                               ;If not, exit
  920.     
  921.     mov ax,24h                          ;Function 24h - Get mouse information
  922.     int 33h                             ;Call mouse driver
  923.     
  924. @@:
  925.     xor ah,ah                           ;Make sure ah = 0
  926.     mov al,bh                           ;Major version into al
  927.     mov si,[MajorV]
  928.     mov [si],ax                         ;Ax into MajorV%
  929.     mov al,bl                           ;Minor version into al
  930.     mov si,[MinorV]
  931.     mov [si],ax                         ;Ax into MinorV%
  932.     mov al,ch                           ;Mouse type into al
  933.     mov si,[MouseType]
  934.     mov [si],ax                         ;Ax into MouseType%
  935.     mov al,cl                           ;Irq into al
  936.     mov si,[Irq]
  937.     mov [si],ax                         ;Ax into Irq%
  938.     ret
  939.  
  940. MouseGetInfo endp
  941. ;-----------------------------------------------------------------------------
  942.  
  943. MouseSetEvent proc, EventMask:Word
  944.  
  945.     ; This routine sets up a "Mouse Event" handler which can be trapped in
  946.     ; your BASIC program via "ON UEVENT".
  947.     
  948.     ; The following are the available events that can be trapped. Any
  949.     ; combination of events are acceptable. Each event has a value
  950.     ; associated with it. Define the desired event by assigning its
  951.     ; value to the EventMask% parameter when calling this routine. Combinations
  952.     ; of events can be obtained by adding the values of the respective events.
  953.     ; for example, to set an event for "left button release" and "right
  954.     ; button release", simply add the values together: 4 + 16 = 20.
  955.     
  956.     ;       1 = Any mouse movement
  957.     ;       2 = Left button pressed
  958.     ;       4 = Left button released
  959.     ;       8 = Right button pressed
  960.     ;      16 = Right button released
  961.     ;      32 = Center button pressed
  962.     ;      64 = Center button released
  963.     
  964.     ;From BASIC:
  965.     ;
  966.     ;   DECLARE SUB MouseSetEvent (EventMask%)
  967.     ;   CALL MouseSetEvent(20)          'Traps left or right button release
  968.     ;
  969.     ;   ON UEVENT GOSUB MouseEvent
  970.     ;   UEVENT ON
  971.     ;
  972.     ;   DO                              'Continue processing event until
  973.     ;       A$ = INKEY$                 ' a key is pressed.
  974.     ;   LOOP UNTIL LEN(A$)
  975.     ;   END
  976.     ;
  977.     ;MouseEvent:
  978.     ;  CALL MouseGetEventInfo(Event%, Lb%, Rb%, Cb%, Row%, Column%)
  979.     ;  PRINT "Mouse event occurred: - ";
  980.     ;  IF Event% AND 4 THEN
  981.     ;     PRINT "Left Button was released."
  982.     ;  END IF
  983.     ;  IF Event% AND 16 THEN
  984.     ;     PRINT "Right Button was released."
  985.     ;  END IF
  986.     ;  PRINT "Mouse location:"; Row%; ","; Column%
  987.     ;RETURN
  988.  
  989.     cmp cs:MouseButtons,0               ;Has mouse been initialized?
  990.     jz @F                               ;If not, exit
  991.     
  992.     Assume ds:Dgroup    
  993.     mov bx,[EventMask]                  ;Pointer to EventMask% into bx
  994.     mov cx,[bx]                         ;EventMask% into cx
  995.     jcxz @F                             ;Don't allow zero. Use MouseCancelEvent
  996.     and cx,127                          ; to disable handler. Strip unused bits
  997.     call _SetEventHandler               ;Turn on mouse event handler
  998.     mov cs:UEventActive,-1              ;Set our flag indicating active event
  999.  
  1000. @@: ret                                 ;Back to BASIC.
  1001.     
  1002. MouseSetEvent endp
  1003.  
  1004. ;-----------------------------------------------------------------------------
  1005.  
  1006. MouseCancelEvent proc
  1007.  
  1008.     ; Cancels (disables) active mouse event handler.
  1009.     
  1010.     ; From BASIC:
  1011.     ;
  1012.     ;   DECLARE SUB MouseCancelEvent ()         'Optional
  1013.     ;   CALL MouseCancelEvent                   'Or if declare is present,
  1014.     ;   MouseCancelEvent
  1015.     
  1016.     cmp cs:UEventActive,0               ;Is the event handler active?
  1017.     jz @F                               ;If not, exit
  1018.     
  1019.     xor cx,cx                           ;Zero cx (Disables handler)
  1020.     call _SetEventHandler               ;Call the mouse driver
  1021.     mov cs:UEventActive,0               ;Zero our flag
  1022.     
  1023. @@: ret                                 ;Back to BASIC
  1024.     
  1025. MouseCancelEvent endp
  1026.  
  1027. ;-----------------------------------------------------------------------------
  1028.  
  1029. MouseGetEventInfo proc, Event:Word, Lb:Word, Rb:Word, Cb:Word, Row%:Word, Column:Word
  1030.  
  1031.     ;Returns the values set during the last mouse event
  1032.     
  1033.     ;From BASIC:
  1034.     ;
  1035.     ;   DECLARE SUB MouseGetEventInfo(Event%, Lb%, Rb%, Cb%, Row%, Column%)
  1036.     ;   CALL MouseGetEventInfo(Event%, Lb%, Rb%, Cb%, Row%, Column%)
  1037.  
  1038.     ; Event% is bit-mapped and indicates what condition(s) triggered the
  1039.     ; mouse event. Just "AND" Event% with a value associated with one of
  1040.     ; your defined events. If the result is non-zero then that was what
  1041.     ; triggered the event. For example:
  1042.     ;
  1043.     ;   PRINT "Event cause: ";
  1044.     ;   IF Event% AND 4 THEN                    '4 is value for "left release"
  1045.     ;      PRINT "Left button was released."
  1046.     ;   ELSEIF Event% AND 16 THEN               '16 is value for "right release"
  1047.     ;      PRINT "Right button was released."
  1048.     ;   END IF
  1049.  
  1050.     ; See MouseSetEvent for a complete listing of all available events and
  1051.     ; their respective values.
  1052.     
  1053.     ; The other parameters reflect the state of the mouse at the time of the
  1054.     ; last event. See MouseSetStatus for info on how to interpret their
  1055.     ; meanings.
  1056.  
  1057.     xor ax,ax                           ;Zero registers so zero results will
  1058.     mov bx,ax                           ; returned if the mouse has not been
  1059.     mov cx,ax                           ; initialized.
  1060.     mov dx,ax
  1061.     
  1062.     cmp cs:MouseButtons,0               ;Has the mouse been initialized?
  1063.     jz @F                               ;If not, exit
  1064.     
  1065.     mov bx,cs:ButtonState               ;Load registers with current values
  1066.     mov cx,cs:HorizPos                  ; set by the last event.
  1067.     mov dx,cs:VertPos
  1068.     
  1069.     call _CommonFromPixels              ;Convert to row/column, if needed
  1070.     
  1071. @@:
  1072.     call _SetupReturn                   ;Load register contents into params
  1073.     mov ax,cs:EventCause                 ; for return to BASIC.
  1074.     Assume ds:Dgroup
  1075.     mov bx,[Event]                      ;Pointer to Event% into bx
  1076.     mov [bx],ax                         ;Event mask into Event%
  1077.     ret    
  1078.  
  1079. MouseGetEventInfo endp
  1080.     
  1081. ;-----------------------------------------------------------------------------
  1082.  
  1083. MouseExit proc
  1084.  
  1085.     ; This code should be called prior to program termination. It performs
  1086.     ; such tasks as releasing memory allocated by the mouse routines and
  1087.     ; unhooking the mouse routines from the mouse driver's "User Defined Event"
  1088.     ; handler. Failure to call this routine prior to program termination
  1089.     ; could result is a system lockup if the MouseSetEvent routine has been
  1090.     ; previously called and the MouseCancelEvent routine was not.
  1091.     
  1092.     ; During the call to the MouseReset routine, we attempted to add this
  1093.     ; this routine to BASIC's B_OnExit chain. This allows BASIC itself to call
  1094.     ; this code when your program terminates or restarts. In other words,
  1095.     ; you probably won't have to worry about it. It is a pretty rare occurance
  1096.     ; that the B_OnExit call would fail - more than 32 other procedures would
  1097.     ; have to be registered before it would fail.
  1098.     
  1099.     ; But for those faint of heart, we've gotcha covered. The function 
  1100.     ; MouseOnExit% returns true if we are successfully included
  1101.     ; in the B_OnExit chain. If it returns false, the you need to call
  1102.     ; this routine (MouseExit) manually before your program terminates. For
  1103.     ; example:
  1104.     
  1105.     ; IF NOT MouseOnExit% THEN
  1106.     ;    CALL MouseExit
  1107.     ; END IF
  1108.     ; END
  1109.  
  1110.     cmp cs:MouseButtons,0               ;Has mouse been initialized?
  1111.     jz @F                               ;If not, get out
  1112.  
  1113.     cmp cs:StateSegment,0               ;Has mouse state been saved and not
  1114.     jz CheckEventHandler                ; restored? If not, continue.
  1115.     
  1116.     mov es,cs:StateSegment              ;Put its segment into es
  1117.     mov ax,4900h                        ;Dos function 49h - Release memory
  1118.     int 21h                             ;Call Dos.
  1119.  
  1120.     mov cs:StateSegment,0               ;Zero the flag in case in the IDE
  1121.     
  1122.     xor ax,ax                           ;Set up for call to SETMEM. Give back
  1123.     push ax                             ; memory to BASIC. This is necessary
  1124.     push cs:SaveBytes                   ; in case we are in the environment
  1125.     call b$SetM                         ; where the memory isn't automatically
  1126.                                         ; reclaimed.
  1127. CheckEventHandler:
  1128.     cmp cs:UEventActive,0               ;Is a mouse event sent?
  1129.     jz @F                               ;If not, exit
  1130.  
  1131.     xor cx,cx                           ;Cancel mouse event handler
  1132.     call _SetEventHandler
  1133.     
  1134.     mov cs:UEventActive,0               ;Clear our event flag
  1135.     mov cs:OnExitSet,0                  ;Clear our OnExit flag. (We're
  1136.                                         ; supposedly terminating the program)
  1137. @@: ret                                 ;Back to whoever called us
  1138.         
  1139. MouseExit endp
  1140.     
  1141. ;-----------------------------------------------------------------------------
  1142. ; The procedures listed below are called internally by the various mouse
  1143. ; routines. Do not attempts to call these from BASIC.
  1144. ;-----------------------------------------------------------------------------
  1145.  
  1146. _CommonToPixels proc near
  1147.  
  1148.     ;Converts row/column coordinates to pixel based coordinates.
  1149.     
  1150.     cmp cs:PixelsOn,-1                  ;Are we in the Pixels mode?
  1151.     jz @F                               ;If so, skip.
  1152.     
  1153.     call _GetCharSize                   ;Returns size of char in pixels
  1154.     
  1155.     xchg ax,dx                          ;Vertical location into ax
  1156.     dec ax                              ;Decrement by 1 for base 0 calculation
  1157.     xor dx,dx                           ;Zero dx for multiplication
  1158.     mul bx                              ;Multiply
  1159.     xchg ax,cx                          ;Horiz position into ax and result of
  1160.     dec ax                              ; last calculation into cx.
  1161.     xor dx,dx                           ;Zero dx again for another multiply
  1162.     mov bx,8                            ;Multiply by 8 pixels wide
  1163.     mul bx
  1164.     xchg dx,cx                          ;Results of first calc back into dx
  1165.     xchg ax,cx                          ;Result of last calc into cx
  1166.     
  1167. @@: ret
  1168.  
  1169. _CommonToPixels endp
  1170.  
  1171. ;-----------------------------------------------------------------------------
  1172.  
  1173. _CommonFromPixels proc near uses es
  1174.  
  1175.     ;Internal routine that converts mouse pixel corrdinates into row/column
  1176.     ;coordinates.
  1177.     
  1178.     ;Enter with BX = button status
  1179.     ;           CX = Horizontal (X) position in pixels
  1180.     ;           DX = Vertical   (Y) position in pixels
  1181.     ;Returns:   AH = Left button status
  1182.     ;           AL = Right Button Status
  1183.     ;           BH = Center button status
  1184.  
  1185.     cmp cs:PixelsOn,-1                  ;Is pixel mode on?
  1186.     jz @F                               ;If so, skip the row/col conversion
  1187.  
  1188.     push bx                             ;Save button status for now
  1189.     call _GetCharSize                   ;Interrogate system for char size
  1190.     xchg ax,dx                          ;Vertical position into ax
  1191.     xor dx,dx                           ;Zero dx for division
  1192.     div bx                              ;Divide by char height -> ax
  1193.     inc ax                              ;Add 1
  1194.     push ax                             ;Save result for now
  1195.     mov bx,8                            ;Character width into bx for divide
  1196.     xchg cx,ax                          ;Put horizontal position into ax
  1197.     xor dx,dx                           ;Zero dx again for division
  1198.     div bx                              ;Divide position by char width -> ax
  1199.     inc ax                              ;Add 1
  1200.     xchg cx,ax                          ;Result back into cx
  1201.     pop dx                              ;Result of first calculation into dx
  1202.     pop bx                              ;Restore button status.
  1203.  
  1204. @@:
  1205.     call _XlateButtonStatus             ;Convert bx into Lb, Rb and Cb
  1206.     ret                                 ;We're finished here.
  1207.     
  1208. _CommonFromPixels endp
  1209.  
  1210. ;-----------------------------------------------------------------------------
  1211.  
  1212. _GetCharSize proc near
  1213.  
  1214.     ;Internal routine that returns the character height (in scan lines)
  1215.     ;in the BX register.
  1216.     
  1217.     push ds                             ;Save ds
  1218.     mov ax,40h
  1219.     Assume Ds:Nothing
  1220.     mov ds,ax                           ;Point ds to BIOS Data Area
  1221.     mov bl,byte ptr ds:[84h]            ;Ega/Vga rows into bl
  1222.     cmp bl,0                            ;If non-zero, we are on a EGA/MCGA/VGA
  1223.     jz CgaOrMono                        ;If zero, it's a CGA, mono, or Herc.
  1224.     mov bl,ds:[49h]                     ;Get current video mode
  1225.     cmp bl,3                            ;If >3 we're in graphics mode
  1226.     jg GraphicsMode                     ;Jump to that code, if needed
  1227.     mov bx,8                            ;If in text mode, char size is 8
  1228.     jmp short HeightExit
  1229.     
  1230. GraphicsMode:
  1231.     mov bx,ds:[85h]                     ;Get info right from BIOS data area.
  1232.     jmp short HeightExit                ;We're finished.
  1233.     
  1234. CgaOrMono:
  1235.     mov bx,8                           ;Always 8 high
  1236.     
  1237. HeightExit:
  1238.     pop ds                              ;Restore ds as to not freak anyone out
  1239.     ret                                 ;Back to whatever procedure called us
  1240.     
  1241. _GetCharSize endp
  1242.  
  1243. ;-----------------------------------------------------------------------------
  1244.  
  1245. _XlateButtonStatus proc near
  1246.  
  1247.     ;Converts BX into button status info. Returned in AH (LB), AL (RB), and
  1248.     ; BH (CB).
  1249.     
  1250.     xor ax,ax                           ;Zero ax and bh (assume all off)
  1251.     mov bh,ah
  1252.     test bl,1                           ;Is left button pressed?
  1253.     jz CheckRight                       ;If not, check next button
  1254.     not ah                              ;If it is pressed, make ah = -1
  1255.  
  1256. CheckRight:
  1257.     test bl,2                           ;Is the right button pressed?
  1258.     jz CheckCenter                      ;If not, check center button
  1259.     not al                              ;If it is pressed, make al = -1
  1260.     
  1261. CheckCenter:
  1262.     test bl,4                           ;Is the center button pressed?
  1263.     jz ExitButtonStatus                 ;If not, exit.
  1264.     not bh                              ;If so, make bh=-1
  1265.     
  1266. ExitButtonStatus:
  1267.     ret
  1268.     
  1269. _XlateButtonStatus endp
  1270.  
  1271. ;-----------------------------------------------------------------------------
  1272.  
  1273. _SetupReturn proc near
  1274.  
  1275.     ; Internal routine that takes register values, coverts them to words,
  1276.     ; and loads them into BASIC parameters for return.
  1277.  
  1278.     Assume ds:DGroup
  1279.     push ax                             ;Save two copies of ax
  1280.     push ax               
  1281.     mov al,bh                           ;move bh into al (so we can use bx)
  1282.     cbw                                 ;Convert al to a word (extends sign)
  1283.     mov bx,[bp+10]                      ;Pointer to Cb% into bx
  1284.     mov [bx],ax                         ;Center button status into Cb%
  1285.     pop ax
  1286.     cbw                                 ;Convert al to word (Right button)
  1287.     mov bx,[bp+12]                      ;Pointer to Rb% into bx
  1288.     mov [bx],ax                         ;Right button status into Rb%
  1289.     pop ax
  1290.     mov al,ah                           ;Left button status into al
  1291.     cbw                                 ;Convert it to a word
  1292.     mov bx,[bp+14]                      ;Pointer to Lb% into bx
  1293.     mov [bx],ax                         ;Left button status into Lb%
  1294.     mov bx,[bp+8]                       ;Pointer to Row% into bx
  1295.     mov [bx],dx                         ;Vertical position into Row%
  1296.     mov bx,[bp+6]                       ;Pointer to Column% into bx
  1297.     mov [bx],cx                         ;Horizontal position into Row%
  1298.     ret
  1299.  
  1300. _SetupReturn endp
  1301.  
  1302. ;-----------------------------------------------------------------------------
  1303.  
  1304. _MouseEventHandler proc uses ds
  1305.  
  1306.     ; This routine is called by the mouse driver when the MouseSetEvent routine
  1307.     ; has been previously called. Each time, we call BASIC's SetUEvent routine,
  1308.     ; store the mouse button status and location for later retrieval - 
  1309.     ; presumably during the BASIC program's "ON UEVENT" handler.
  1310.  
  1311.     ; On entry, the registers are configured as follows:
  1312.     ;
  1313.     ; AX - Mouse event flag(s). See MouseSetEvent for more info.
  1314.     ; BX - Current button status
  1315.     ; CX - Horizontal (X) mouse pointer location
  1316.     ; DX - Vertical (Y) mouse pointer location
  1317.     ; SI - Last raw vertical mickey count
  1318.     ; DI - Last raw horizontal mickey count
  1319.     ; DS - Mouse driver data segment    
  1320.  
  1321.     mov cs:EventCause,ax                ;Save event mask (cause of event)
  1322.     mov cs:ButtonState,bx               ;Save button state
  1323.     mov cs:VertPos,dx                   ;Current vertical position
  1324.     mov cs:HorizPos,cx                  ;Current horizontal position
  1325.     push ss
  1326.     pop ds                              ;Point ds to DGROUP for call
  1327.     call SetUEvent                      ;Tell BASIC a "UEvent" occurred. 
  1328.     ret                                 ;Return to mouse driver
  1329.     
  1330. _MouseEventHandler endp
  1331.  
  1332. ;-----------------------------------------------------------------------------
  1333.  
  1334. _SetEventHandler proc near
  1335.  
  1336.     ; Internal routine - Used to establish or cancel an active mouse 
  1337.     ; event handler. 
  1338.     
  1339.     ; Input: CX - Event Mask. 0 Cancels, 1-127 establishes
  1340.  
  1341.     mov ax,0ch                          ;Function 0Ch - Set mouse event handler
  1342.     push cs                             ;Point to the one we want to disable.
  1343.     pop es
  1344.     mov dx,offset _MouseEventHandler
  1345.     int 33h                             ;Call the mouse driver
  1346.     ret    
  1347.  
  1348. _SetEventHandler endp
  1349.  
  1350. ;-----------------------------------------------------------------------------
  1351.     end                                 ;End of assembly source file
  1352.