home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / progmisc / nfsrc21.zip / MOUSE1.PRG < prev    next >
Text File  |  1992-10-17  |  46KB  |  1,557 lines

  1. /*
  2.  * File......: MOUSE1.PRG
  3.  * Author....: Leo Letendre
  4.  * CIS ID....: 73607,233
  5.  * Date......: $Date:   17 Oct 1992 16:28:58  $
  6.  * Revision..: $Revision:   1.9  $
  7.  * Log file..: $Logfile:   C:/nanfor/src/mouse1.prv  $
  8.  * 
  9.  * This is an original work by Robert DiFalco and is placed in the
  10.  * public domain.
  11.  *
  12.  * Modification history:
  13.  * ---------------------
  14.  *
  15.  * $Log:   C:/nanfor/src/mouse1.prv  $
  16.  * 
  17.  *    Rev 1.9   17 Oct 1992 16:28:58   GLENN
  18.  * Leo cleaned up documentation blocks.
  19.  * 
  20.  *    Rev 1.8   28 Sep 1992 01:38:14   GLENN
  21.  * Leo added FT_MGETSENS(), FT_MSETSENS(), FT_MSETPAGE(), FT_MGETPAGE(),
  22.  * and FT_MVERSION().
  23.  * 
  24.  * 
  25.  *    Rev 1.7   01 Jul 1992 01:45:18   GLENN
  26.  * Leo added documentation to FT_MDEFCRS and others. Added FT_MCONOFF(),
  27.  * FT_MINIT(), FT_MGETCOORD() and FT_MSETCOORD().  Restructured
  28.  * FT_MGETX() and FT_MGETY() for possible speed improvement and MAIN to
  29.  * better demonstrate some of the concerns when programming the mouse. 
  30.  * Added ability to change the number of rows and columns to demonstrate
  31.  * use in 43, 50 row mode etc. which is now supported in FT_MRESET() and
  32.  * FT_MINIT().
  33.  * 
  34.  *    Rev 1.6   23 Sep 1991 01:14:38   GLENN
  35.  * Corrected errors in syntax documention for FT_MBUTPRS() and FT_MDBLCLK(),
  36.  * found by Nantucket's Steve Silverwood.
  37.  * 
  38.  *    Rev 1.5   17 Aug 1991 15:34:52   GLENN
  39.  * Don Caton fixed some spelling errors in the doc
  40.  * 
  41.  *    Rev 1.4   15 Aug 1991 23:06:24   GLENN
  42.  * Forest Belt proofread/edited/cleaned up doc
  43.  * 
  44.  *    Rev 1.3   17 Jul 1991 22:28:40   GLENN
  45.  * Leo fixed a potential bug in ft_mcursor().
  46.  * 
  47.  *    Rev 1.2   27 May 1991 13:40:30   GLENN
  48.  * Leo Letendre sent me a revision of MOUSE1.PRG where he built in support
  49.  * for a three-button mouse, and revised the "double click" detection 
  50.  * algorithm.
  51.  *  
  52.  * Brought in compliance with new ft_int86().
  53.  * 
  54.  *    Rev 1.1   11 May 1991 00:16:48   GLENN
  55.  * ft_mgetpos() had a bug where the x and y coordinates were reversed. 
  56.  * Changed x coordinate to aRegs[3] and y coordinate to aRegs[4], just
  57.  * like in ft_msetpos().
  58.  * 
  59.  *    Rev 1.0   01 Apr 1991 01:01:48   GLENN
  60.  * Nanforum Toolkit
  61.  *
  62.  */
  63.  
  64.  
  65. // The original mouse routines were written by Robert diFalco but
  66. // Leo Letendre has made such major additions and modifications
  67. // and fixes that I've given him sole credit. -- G. Scott
  68.  
  69.  
  70. #include "FTINT86.CH"
  71.  
  72. static aReg[INT86_MAX_REGS]
  73. static lCrsState:=.F.
  74. static lMinit:=.F.
  75.  
  76. #ifdef FT_TEST
  77.  
  78.   FUNCTION MAIN(nRow,nCol)
  79.  
  80. * Pass valid row and column values for different video modes to change modes
  81.  
  82.      local nX, nY, cSavClr
  83.      local cSavScr := savescreen( 0, 0, maxrow(), maxcol() )
  84.      local nXm, nYm
  85.      local nSaveRow:=MAXROW()+1, nSaveCol:=MAXCOL()+1
  86.      local nMinor, nType, nIRQ
  87.      local aType:={"Bus","Serial","InPort","PS/2","HP"}
  88.      local nHoriz, nVert, nDouble
  89.      local nTime
  90.  
  91.     IF nRow=NIL
  92.         nRow=MAXROW()+1
  93.     ELSE
  94.         nRow=VAL(nRow)
  95.     ENDIF
  96.  
  97.     IF nCol=NIL
  98.         nCol=MAXCOL()+1
  99.     ELSE
  100.         nCol=VAL(nCol)
  101.     ENDIF
  102.  
  103.     IF .NOT.SETMODE(nRow,nCol)
  104.         @maxrow(),0 SAY "Mode Change unsuccessful:"+STR(nRow,2,0)+" by";
  105.             +STR(nCol,3,0)
  106.         RETURN NIL
  107.     ENDIF
  108.  
  109.      if empty( FT_MINIT() )
  110.         @ maxrow(), 0 say "Mouse driver is not installed!"
  111.         SETMODE(nSaveRow,nSaveCol)
  112.         return ""
  113.      endif
  114.  
  115.      * ..... Set up the screen
  116.      cSavClr := setcolor( "w/n" )
  117.      @ 0,0,maxrow(),maxcol() box "░░░░░░░░░"
  118.  
  119.      setcolor( "GR+/RB" )
  120.      scroll( 7,2,19,63,0 )
  121.      @ 7,2 to 20,63
  122.  
  123.      @ 17, 10 to 19, 40 double
  124.  
  125.      setcolor( "N/W" )
  126.      @ 18, 11 say "  Double Click here to Quit  "
  127.  
  128.      setcolor( "GR+/RB" )
  129.  
  130.      * ..... Start the demo
  131.  
  132.     @MAXROW(),0 SAY "Driver version: "+;
  133.         ALLTRIM(STR(FT_MVERSION(@nMinor,@nType,@nIRQ),2,0))+"."+;
  134.         ALLTRIM(STR(nMinor,2,0))
  135.      @ ROW(),COL() SAY " "+aType[nType]+" mouse using IRQ "+STR(nIRQ,1,0)
  136.  
  137.      FT_MGETSENS(@nHoriz,@nVert,@nDouble)  // Get the current sensitivities
  138.     FT_MSETSENS(70,70,60)    // Bump up the sensitivity of the mouse
  139.  
  140.      FT_MSHOWCRS()
  141.      FT_MSETCOORD(10,20)  // just an arbitrary place for demo
  142.  
  143. * put the unchanging stuff
  144.  
  145.      devpos( 9, 10 )
  146.      devout( "FT_MMICKEYS :" )
  147.  
  148.      devpos( 10, 10 )
  149.      devout( "FT_MGETPOS  :" )
  150.  
  151.      devpos( 11, 10 )
  152.      devout( "FT_MGETX    :" )
  153.    
  154.      devpos( 12, 10 )
  155.      devout( "FT_MGETY    :")
  156.    
  157.      devpos( 13, 10 )
  158.      devout( "FT_MGETCOORD:" )
  159.    
  160.      devpos( 14, 10 )
  161.      devout( "FT_MBUTPRS  :" )
  162.    
  163.      devpos( 16, 10 )
  164.      devout( "FT_MBUTREL  :" )
  165.  
  166.      nX := nY := 1
  167.      do while .t.
  168.  
  169. * If we are not moving then wait for movement.
  170. * This whole demo is a bit artificial in its requirements when compared 
  171. * to a "normal" CLIPPER program so some of these examples are a bit out of
  172. * the ordinary.
  173.    
  174.         DO WHILE nX=0.AND.nY=0 
  175.              FT_MMICKEYS( @nX, @nY )
  176.         ENDDO
  177. * tell the mouse driver where updates will be taking place so it can hide
  178. * the cursor when necessary. 
  179.  
  180.         FT_MCONOFF( 9, 23, 16, 53 )
  181.         nTime=-1
  182.  
  183.         devpos( 9, 23 )
  184.         devout( nX )
  185.         devout( nY )
  186.  
  187.         devpos( 10, 23 )
  188.         DEVOUT( FT_MGETPOS( @nX, @nY ) )
  189.         devout( nX )
  190.         devout( nY )
  191.  
  192.         devpos( 11, 23 )
  193.         DEVOUT(  FT_MGETX() )
  194.  
  195.         devpos( 12, 23 )
  196.         DEVOUT( FT_MGETY() )
  197.  
  198.         devpos( 13, 23 )
  199.         devout( FT_MGETCOORD( @nX, @nY ) )
  200.         devout ( nX )
  201.         devout ( nY )
  202.  
  203.         nX:=nY:=0
  204.         devpos( 14, 23 )
  205.         DEVOUT( FT_MBUTPRS(1) )
  206.         DEVOUT( FT_MBUTPRS(0,, nX, nY) )
  207.         devpos( 15, 23 )
  208.  
  209. * show only the last Press since it flashes by so quickly
  210.  
  211.         IF nX!=0.OR.nY!=0
  212.              devout( nX )
  213.              devout( nY )
  214.         endif
  215.  
  216.         nX:=nY:=0
  217.         devpos( 16, 23 )
  218.         devout( FT_MBUTREL(0,, @nX, @nY) )
  219.  
  220. * show only the last release since it flashes by so quickly
  221.  
  222.         if nX!=0.OR.nY!=0
  223.              devout( nX )
  224.              devout( nY )
  225.         endif
  226.  
  227. * Restore the cursor if it has been hidden
  228.  
  229.         FT_MSHOWCRS()
  230.  
  231.         if FT_MINREGION( 18, 11, 18, 39 )
  232.  
  233. * Change the type of cursor when in the box. Just slightly different than the
  234. * normal. The character is shown in high intensity.
  235.  
  236.            FT_MDEFCRS(0,32767,32512)
  237.            if FT_MDBLCLK(2,0,0.8)  
  238.               exit
  239.            endif
  240.         endif
  241.  
  242.         if FT_MINREGION( 18, 11, 18, 39 )
  243.  
  244. * Change the type of cursor when in the box. Just slightly different than the
  245. * normal. The character is shown in high intensity.
  246.  
  247.            FT_MDEFCRS(0,32767,32512)
  248.         else
  249.  
  250. * Put the cursor back to normal mode
  251.  
  252.            FT_MDEFCRS(0,30719,30464)
  253.         endif
  254.  
  255.         FT_MMICKEYS( @nX, @nY )
  256.      enddo
  257.  
  258.      FT_MHIDECRS()
  259.  
  260.      SETMODE(nSaveRow,nSaveCol)
  261.      setcolor( cSavClr )
  262.      restscreen( 0, 0, maxrow(), maxcol(), cSavScr )
  263.      devpos( maxrow(), 0 )
  264.  
  265. // Reset sensitivity
  266.  
  267.      FT_MSETSENS(nHoriz, nVert, nDouble)
  268.  
  269.   RETURN nil
  270.  
  271.  
  272. #endif 
  273.  
  274.  
  275.  
  276. /*
  277.  * $DOC$         
  278.  * $FUNCNAME$
  279.  *    FT_MINIT()
  280.  * $CATEGORY$
  281.  *    Keyboard/Mouse
  282.  * $ONELINER$
  283.  *    Initialize the mouse driver, vars and return status of mouse
  284.  * $SYNTAX$
  285.  *    FT_MINIT() -> lMouseStatus
  286.  * $ARGUMENTS$
  287.  *    NONE
  288.  * $RETURNS$
  289.  *    An logical representing the mouse status (.F. == mouse not installed)
  290.  * $DESCRIPTION$
  291.  *    Initializes the mouse drive, associated variables and returns mouse 
  292.  *    status. It checks to see if the mouse has been previously initialized
  293.  *    and if so it does not reinitialize. The row and column limits of mouse
  294.  *    movement is set to the maximum for the current video mode. 
  295.  *    Use FT_MSHOWCRS() to display the mouse cursor.
  296.  * $EXAMPLES$
  297.  *    IF .NOT. FT_MINIT()
  298.  *       ? "No mouse driver is installed"
  299.  *    ENDIF
  300.  * $SEEALSO$
  301.  *    FT_MRESET()
  302.  * $END$
  303.  */
  304.  
  305. FUNCTION FT_MINIT()
  306.  
  307. * If not previously initialized then try
  308.  
  309.    IF !lMinit
  310.     lMinit=(FT_MRESET()!=0)
  311.    ELSE
  312. * Reset maximum x and y limits
  313.  
  314.      FT_MYLIMIT(0,8*MAXROW())
  315.      FT_MXLIMIT(0,8*MAXCOL())
  316.    ENDIF
  317.  
  318.  
  319. RETURN lMinit
  320.  
  321. /*
  322.  * $DOC$         
  323.  * $FUNCNAME$
  324.  *    FT_MRESET()
  325.  * $CATEGORY$
  326.  *    Keyboard/Mouse
  327.  * $ONELINER$
  328.  *    Reset mouse driver and return status of mouse
  329.  * $SYNTAX$
  330.  *    FT_MRESET() -> nMouseStatus
  331.  * $ARGUMENTS$
  332.  *    NONE
  333.  * $RETURNS$
  334.  *    An integer representing the mouse status (0 == mouse not installed)
  335.  * $DESCRIPTION$
  336.  *    Resets the mouse driver and returns mouse status. Use FT_MSHOWCRS()
  337.  *    to display the mouse cursor. The mouse is set to allow it to cover the
  338.  *    complete screen (as defined by MAXCOL() and MAXROW()). This is necessary
  339.  *    because at least some versions of the mouse drivers do not operate
  340.  *    according to the documentation when confronted with a 43 or 50 line
  341.  *    screen.
  342.  *
  343.  *    Normally, FT_MINIT() should be used to initialize the mouse since it 
  344.  *    will not reinitialize if already done.
  345.  * $EXAMPLES$
  346.  *    IF Empty( FT_MRESET() )
  347.  *       ? "No mouse driver is installed"
  348.  *    ENDIF
  349.  *  $SEEALSO$
  350.  *     FT_MINIT() FT_MSHOWCRS()
  351.  * $END$
  352.  */
  353.  
  354. FUNCTION FT_MRESET()
  355.  
  356.    aReg[AX] := 0          // set mouse function call 0
  357.    FT_INT86( 51, aReg )  // execute mouse interrupt
  358.    lCrsState=.F.         // Cursor is off after reset
  359.  
  360. * Reset maximum x and y limits
  361.  
  362.    FT_MYLIMIT(0,8*MAXROW())
  363.    FT_MXLIMIT(0,8*MAXCOL())
  364.  
  365. RETURN aReg[AX]            // return status code
  366.  
  367.  
  368. /* $DOC$         
  369.  * $FUNCNAME$
  370.  *    FT_MCURSOR()
  371.  * $CATEGORY$
  372.  *    Keyboard/Mouse
  373.  * $ONELINER$
  374.  *    Set the mouse cursor
  375.  * $SYNTAX$
  376.  *    FT_MCURSOR( [ <lState> ] ) -> lCursorState
  377.  * $ARGUMENTS$
  378.  *    <lState> is a logical indicating whether to set the mouse cursor on.
  379.  *             .T. - set mouse cursor on 
  380.  *             .F. - set mouse cursor off
  381.  *             If omitted, no change is made to cursor state
  382.  * $RETURNS$
  383.  *    A logical indicating the previous mouse cursor state.
  384.  * $DESCRIPTION$
  385.  *    This function works like most Clipper state functions.  If no value
  386.  *    is sent to FT_MCURSOR() it will return the state of the mouse cursor.
  387.  * $EXAMPLES$
  388.  *    IF !( FT_MCURSOR() )
  389.  *       FT_MCURSOR( .T. )
  390.  *    ENDIF
  391.  * $END$
  392.  */
  393.  
  394. FUNCTION FT_MCURSOR( lState )
  395.    local lSavState := lCrsState
  396.  
  397.    if VALTYPE(lState)="L"
  398.       if ( lCrsState := lState )
  399.          FT_MSHOWCRS()
  400.       else
  401.          FT_MHIDECRS()
  402.       endif
  403.    ENDIF
  404.  
  405. RETURN lSavState
  406.  
  407.  
  408. /* $DOC$         
  409.  * $FUNCNAME$
  410.  *    FT_MSHOWCRS()
  411.  * $CATEGORY$
  412.  *    Keyboard/Mouse
  413.  * $ONELINER$
  414.  *    Increment internal cursor flag and display mouse cursor
  415.  * $SYNTAX$
  416.  *    FT_MSHOWCRS() -> NIL
  417.  * $ARGUMENTS$
  418.  *    NONE
  419.  * $RETURNS$
  420.  *    NIL
  421.  * $DESCRIPTION$
  422.  *    Displays the mouse cursor. Make sure to turn the mouse cursor off
  423.  *    when redrawing screens.  The mouse cursor dutifully saves the screen
  424.  *    under it, so if you draw over the mouse cursor it will create a "hole"
  425.  *    in your screen when you move the mouse cursor.
  426.  *
  427.  *    Note: A call to FT_MHIDECRS() decrements a mouse driver variable
  428.  *    which indicates whether the cursor is shown. The cursor is visible
  429.  *    only when the variable = 0. Thus multiple calls to FT_MHIDECRS() 
  430.  *    require an equal number of calls to FT_MSHOWCRS() before the cursor
  431.  *    will again be visible. Once the variable is 0 calls to FT_MSHOWCRS()
  432.  *    does not increment the variable above 0.
  433.  * $EXAMPLES$
  434.  *    IF Empty( FT_MRESET() )
  435.  *       FT_MSHOWCRS()
  436.  *    ENDIF
  437.  *  $SEEALSO$
  438.  *     FT_MHIDECRS() FT_MCONOFF()
  439.  * $END$
  440.  */
  441.  
  442. FUNCTION FT_MSHOWCRS()
  443.  
  444.    aReg[AX] := 1         // set mouse function call 1
  445.    FT_INT86( 51, aReg ) // execute mouse interrupt
  446.    lCrsState := .t.
  447.  
  448. RETURN NIL              // no output from function
  449.  
  450.  
  451.  
  452. /*
  453.  * $DOC$         
  454.  * $FUNCNAME$
  455.  *    FT_MHIDECRS()
  456.  * $CATEGORY$
  457.  *    Keyboard/Mouse
  458.  * $ONELINER$
  459.  *    Decrement internal mouse cursor flag and hide mouse cursor
  460.  * $SYNTAX$
  461.  *    FT_MHIDECRS() -> NIL
  462.  * $ARGUMENTS$
  463.  *    NONE
  464.  * $RETURNS$
  465.  *    NIL
  466.  * $DESCRIPTION$
  467.  *    Hides the mouse cursor. Make sure to turn the mouse cursor off when
  468.  *    redrawing screens.  The mouse cursor dutifully saves the screen
  469.  *    under it, so if you draw over the mouse cursor it will create a
  470.  *    "hole" in your screen when you move the mouse cursor.
  471.  *
  472.  *    Note: A call to FT_MHIDECRS() decrements a mouse driver variable
  473.  *    which indicates whether the cursor is shown. The cursor is visible
  474.  *    only when the variable = 0. Thus multiple calls to FT_MHIDECRS() 
  475.  *    require an equal number of calls to FT_MSHOWCRS() before the cursor
  476.  *    will again be visible. Once the variable is 0 calls to FT_MSHOWCRS()
  477.  *    does not increment the varaible above 0.
  478.  * $EXAMPLES$
  479.  *    FT_MHIDECRS()
  480.  *    @ 10, 10 to 20, 20
  481.  *    FT_MSHOWCRS()
  482.  *  $SEEALSO$
  483.  *    FT_MSHOWCRS() FT_MCONOFF()
  484.  * $END$
  485.  */
  486.  
  487.  
  488.  
  489. FUNCTION FT_MHIDECRS()   // decrement internal cursor flag and hide cursor
  490.  
  491.    aReg[AX] := 2          // set mouse function call 2
  492.    FT_INT86( 51, aReg )  // execute mouse interrupt
  493.    lCrsState := .f.
  494. RETURN NIL                  // no output from function
  495.  
  496.  
  497. /*
  498.  * $DOC$         
  499.  * $FUNCNAME$
  500.  *    FT_MGETPOS()
  501.  * $CATEGORY$
  502.  *    Keyboard/Mouse
  503.  * $ONELINER$
  504.  *    Get mouse cursor position and button status
  505.  * $SYNTAX$
  506.  *    FT_MGETPOS( @<nX>, @<nY> ) -> nButtonStatus
  507.  * $ARGUMENTS$ 
  508.  *    <nX> is a variable that will receive the mouse X position in virtual
  509.  *    screen coordinates.  It must be passed by reference.
  510.  *
  511.  *    <nY> is a variable that will receive the mouse Y position in virtual
  512.  *    screen coordinates.  It must be passed by reference.
  513.  * $RETURNS$
  514.  *    an integer representing button status
  515.  *
  516.  *          - 0 for no button pressed
  517.  *          - 1 for left pressed
  518.  *          - 2 for right pressed
  519.  *          - 3 for left and right pressed
  520.  *          - 4 for middle pressed
  521.  *          - 5 for left and middle pressed
  522.  *          - 6 for right and middle pressed
  523.  *          - 7 for all three buttons pressed
  524.  * $DESCRIPTION$
  525.  *    Loads cursor position into x and y coordinates passed by reference and
  526.  *    returns the button status. The coordinate system in text mode has
  527.  *    eight virtual coordinates per character cell. Thus x=16 means that you
  528.  *    are in the Row 2. The values returned by this routine when in text mode
  529.  *    and with mouse driver versions 6 and above are multiples of 8. We have
  530.  *    experience with drivers prior to that version
  531.  * $EXAMPLES$
  532.  *    LOCAL nX, nY
  533.  *    LOCAL nButton := FT_MGETPOS( @nX, @nY )
  534.  *    ? "Mouse Row    :", nX
  535.  *    ? "Mouse Column :", nY
  536.  *    ? "Button Status:", nButton
  537.  *  $SEEALSO$
  538.  *    FT_MGETCOORD() FT_MSETPOS() FT_MDEFCRS() FT_MGETX() FT_MGETY()
  539.  * $END$
  540.  */
  541.  
  542.  
  543.  
  544.  
  545. FUNCTION FT_MGETPOS( nX, nY )
  546.  
  547.    nX := if( nX == NIL, 0, nX )
  548.    nY := if( nY == NIL, 0, nY )
  549.  
  550.    aReg[AX] := 3                // set mouse function call 3
  551.    FT_INT86( 51, aReg )        // execute mouse interrupt
  552.    nX := aReg[DX]               // store new x-coordinate
  553.    nY := aReg[CX]               // store new y-coordinate
  554.  
  555. RETURN aReg[BX]                 // return button status
  556.  
  557. /*
  558.  * $DOC$         
  559.  * $FUNCNAME$
  560.  *    FT_MGETCOORD()
  561.  * $CATEGORY$
  562.  *    Keyboard/Mouse
  563.  * $ONELINER$
  564.  *    Get mouse cursor position (text coord.) and button status
  565.  * $SYNTAX$
  566.  *    FT_MGETPOS( @<nX>, @<nY> ) -> nButtonStatus
  567.  * $ARGUMENTS$ 
  568.  *    <nX> is a variable that will receive the mouse X position in text
  569.  *    screen coordinates.  It must be passed by reference.
  570.  *
  571.  *    <nY> is a variable that will receive the mouse Y position in text
  572.  *    screen coordinates.  It must be passed by reference.
  573.  * $RETURNS$
  574.  *    an integer representing button status
  575.  *
  576.  *          - 0 for no button pressed
  577.  *          - 1 for left pressed
  578.  *          - 2 for right pressed
  579.  *          - 3 for left and right pressed
  580.  *          - 4 for middle pressed
  581.  *          - 5 for left and middle pressed
  582.  *          - 6 for right and middle pressed
  583.  *          - 7 for all three buttons pressed
  584.  * $DESCRIPTION$
  585.  *    Loads cursor position into x and y coordinates passed by reference and
  586.  *    returns the button status.
  587.  * $EXAMPLES$
  588.  *    LOCAL nX, nY
  589.  *    LOCAL nButton := FT_MGETCOORD( @nX, @nY )
  590.  *    ? "Mouse Row    :", nX
  591.  *    ? "Mouse Column :", nY
  592.  *    ? "Button Status:", nButton
  593.  *  $SEEALSO$
  594.  *    FT_MGETPOS() FT_MSETPOS() FT_MDEFCRS() FT_MGETX() FT_MGETY()
  595.  * $END$
  596.  */
  597.  
  598. FUNCTION FT_MGETCOORD( nX, nY )
  599.  
  600. * Duplicated code from FT_MGETPOS() for speed reasons
  601.  
  602.    nX := if( nX == NIL, 0, nX )
  603.    nY := if( nY == NIL, 0, nY )
  604.  
  605.    aReg[AX] := 3                // set mouse function call 3
  606.    FT_INT86( 51, aReg )         // execute mouse interrupt
  607.    nX := INT(aReg[DX]/8)        // store new x-coordinate
  608.    nY := INT(aReg[CX]/8)        // store new y-coordinate
  609.  
  610. RETURN aReg[BX]                 // return button status
  611.  
  612.  
  613. /* $DOC$         
  614.  * $FUNCNAME$
  615.  *    FT_MGETX()
  616.  * $CATEGORY$
  617.  *    Keyboard/Mouse
  618.  * $ONELINER$
  619.  *    Get mouse cursor row position
  620.  * $SYNTAX$
  621.  *    FT_MGETX() -> nRowPos
  622.  * $ARGUMENTS$
  623.  *    NONE
  624.  * $RETURNS$
  625.  *    <nRowPos> which is the row position of mouse in virtual screen
  626.  *              coordinates.
  627.  * $DESCRIPTION$
  628.  *    Retrieves mouse's row position in virtual screen coordinates. The
  629.  *    values returned are multiples of 8 when in text mode and with at least
  630.  *    Microsoft drivers 6 and above.
  631.  * $EXAMPLES$ 
  632.  *    ? FT_MGETX()
  633.  *  $SEEALSO$
  634.  *     FT_MGETCOORD() FT_MDEFCRS() FT_MGETPOS() FT_MGETY()
  635.  * $END$
  636.  */
  637.  
  638. FUNCTION FT_MGETX()
  639.  
  640. * Duplicated code from FT_MGETPOS() for speed reasons
  641.  
  642.    aReg[AX] := 3                // set mouse function call 3
  643.    FT_INT86( 51, aReg )        // execute mouse interrupt
  644.  
  645. RETURN( INT(aReg[DX]/8) )       // return x-coordinate
  646.  
  647. /*
  648.  * $DOC$         
  649.  * $FUNCNAME$
  650.  *    FT_MGETY()
  651.  * $CATEGORY$
  652.  *    Keyboard/Mouse
  653.  * $ONELINER$
  654.  *    Get mouse cursor column position
  655.  * $SYNTAX$
  656.  *    FT_MGETY() -> nColPos
  657.  * $ARGUMENTS$
  658.  *    NONE
  659.  * $RETURNS$
  660.  *    <nColPos> Column position of mouse in virtual screen coordinates
  661.  * $DESCRIPTION$
  662.  *    Retrieves mouse's column position in virtual screen coordinates. The
  663.  *    values returned are multiples of 8 when in text mode and with at least
  664.  *    Microsoft drivers 6 and above.
  665.  * $EXAMPLES$
  666.  *    ? FT_MGETY()
  667.  *  $SEEALSO$
  668.  *    FT_MGETCOORD() FT_MDEFCRS() FT_MGETPOS() FT_MGETX()
  669.  * $END$
  670.  */
  671.  
  672. FUNCTION FT_MGETY()
  673.  
  674. * Duplicated code from FT_MGETPOS() for speed reasons
  675.  
  676.    aReg[AX] := 3                // set mouse function call 3
  677.    FT_INT86( 51, aReg )        // execute mouse interrupt
  678.  
  679. RETURN( INT(aReg[CX]/8))        // return y-coordinate
  680.  
  681. /*
  682.  * $DOC$         
  683.  * $FUNCNAME$
  684.  *    FT_MSETPOS()
  685.  * $CATEGORY$
  686.  *    Keyboard/Mouse
  687.  * $ONELINER$
  688.  *    Position the mouse cursor using virtual screen coordinates
  689.  * $SYNTAX$
  690.  *    FT_MSETPOS( <nX>, <nY> ) -> NIL
  691.  * $ARGUMENTS$ 
  692.  *    <nX> is the desired mouse row.
  693.  *
  694.  *    <nY> is the desired mouse column.
  695.  * $RETURNS$
  696.  *    NIL
  697.  * $DESCRIPTION$
  698.  *    Positions mouse cursor on screen. The virtual coordinate system in text 
  699.  *    mode has eight virtual coordinates per character cell. Thus x=16 means 
  700.  *    that you are in the Row 2.
  701.  * $EXAMPLES$
  702.  *    FT_MSETPOS( 10, 20 )     // position mouse cursor at row 10, col 20
  703.  *                             // in virtual screen coordinates
  704.  *  $SEEALSO$
  705.  *    FT_MGETPOS() FT_MGETCOORD() FT_MSETCOORD() FT_MGETX() FT_MGETY()
  706.  * $END$
  707.  */
  708.  
  709. FUNCTION FT_MSETPOS( nX, nY )  // set mouse cursor location
  710.  
  711.    aReg[AX] := 4                // set mouse function call 4
  712.    aReg[CX] := nY               // assign new x-coordinate
  713.    aReg[DX] := nX               // assign new y-coordinate
  714.    FT_INT86( 51, aReg )        // execute mouse interrupt
  715.  
  716. RETURN NIL                     // no function output
  717.  
  718.  
  719. /*
  720.  * $DOC$         
  721.  * $FUNCNAME$
  722.  *    FT_MSETCOORD()
  723.  * $CATEGORY$
  724.  *    Keyboard/Mouse
  725.  * $ONELINER$
  726.  *    Position the mouse cursor using text screen coordinates
  727.  * $SYNTAX$
  728.  *    FT_MSETPOS( <nX>, <nY> ) -> NIL
  729.  * $ARGUMENTS$ 
  730.  *    <nX> is the desired mouse row.
  731.  *
  732.  *    <nY> is the desired mouse column.
  733.  * $RETURNS$
  734.  *    NIL
  735.  * $DESCRIPTION$
  736.  *    Positions mouse cursor on screen using text (normal row and column)
  737.  *    coordinates.
  738.  * $EXAMPLES$
  739.  *    FT_MSETCOORD( 10, 20 )     // position mouse cursor at row 10, col 20
  740.  *                             // in text screen coordinates
  741.  *  $SEEALSO$
  742.  *    FT_MGETPOS() FT_MGETCOORD() FT_MSETPOS() FT_MDEFCRS() FT_MGETX() FT_MGETY()
  743.  * $END$
  744.  */
  745.  
  746. FUNCTION FT_MSETCOORD( nX, nY )  // set mouse cursor location
  747.  
  748.    aReg[AX] := 4                // set mouse function call 4
  749.    aReg[CX] := nY*8             // assign new x-coordinate
  750.    aReg[DX] := nX*8             // assign new y-coordinate
  751.    FT_INT86( 51, aReg )        // execute mouse interrupt
  752.  
  753. RETURN NIL                     // no function output
  754.  
  755. /*
  756.  * $DOC$         
  757.  * $FUNCNAME$
  758.  *    FT_MXLIMIT()
  759.  * $CATEGORY$
  760.  *    Keyboard/Mouse
  761.  * $ONELINER$
  762.  *    Set vertical bounds of mouse using virtual screen coord.
  763.  * $SYNTAX$
  764.  *    FT_MXLIMIT( <nX1>, <nX2> ) -> NIL
  765.  * $ARGUMENTS$
  766.  *    <nX1> is the top row limit.
  767.  *
  768.  *    <nX2> is the bottom row limit.
  769.  * $RETURNS$
  770.  *    NIL
  771.  * $DESCRIPTION$
  772.  *    Set maximum vertical bounds of mouse using virtual screen coordinates.
  773.  * $EXAMPLES$
  774.  *    FT_MXLIMIT( 10, 20 )
  775.  *  $SEEALSO$
  776.  *     FT_MYLIMIT() FT_MINREGION()
  777.  * $END$
  778.  */
  779.  
  780. FUNCTION FT_MXLIMIT( nXMin, nXMax )   // set vertical minimum and maximum coordinates
  781.  
  782.    aReg[AX] = 7                        // set mouse function call 7
  783.    aReg[CX] = nXMin                    // load vertical minimum parameter
  784.    aReg[DX] = nXMax                    // load vertical maximum parameter
  785.    FT_INT86( 51, aReg )               // execute mouse interrupt
  786.  
  787. RETURN NIL
  788.  
  789. /*
  790.  * $DOC$         
  791.  * $FUNCNAME$
  792.  *    FT_MYLIMIT()
  793.  * $CATEGORY$
  794.  *    Keyboard/Mouse
  795.  * $ONELINER$
  796.  *    Set horiz. bounds of mouse using virtual screen coordinates
  797.  * $SYNTAX$
  798.  *    FT_MYLIMIT( <nY1>, <nY2> ) -> NIL
  799.  * $ARGUMENTS$
  800.  *    <nY1> is the left column limit.
  801.  *
  802.  *    <nY2> is the right column limit.
  803.  * $RETURNS$
  804.  *    NIL
  805.  * $DESCRIPTION$
  806.  *    Set maximum horizontal bounds of mouse using virtual screen coordinates.
  807.  * $EXAMPLES$
  808.  *    FT_MYLIMIT( 10, 20 )
  809.  *  $SEEALSO$
  810.  *     FT_MXLIMIT() FT_MINREGION()
  811.  * $END$
  812.  */
  813.  
  814. FUNCTION FT_MYLIMIT( nYMin, nYMax )  // set horizontal minimum and maximum coordinates
  815.  
  816.    aReg[AX] = 8                       // set mouse function call 8
  817.    aReg[CX] = nYMin                   // load horz minimum parameter
  818.    aReg[DX] = nYMax                   // load horz maximum parameter
  819.    FT_INT86( 51, aReg )              // execute mouse interrupt
  820.  
  821. RETURN NIL                           // no function output
  822.  
  823.  
  824. /*
  825.  * $DOC$         
  826.  * $FUNCNAME$
  827.  *    FT_MBUTPRS()
  828.  * $CATEGORY$
  829.  *    Keyboard/Mouse
  830.  * $ONELINER$
  831.  *    Retrieve button press status
  832.  * $SYNTAX$
  833.  *    FT_MBUTPRS( <nButton> [, @nButPrs [, @nX [, @nY] ] ] ) -> nButStatus
  834.  * $ARGUMENTS$
  835.  *    <nButton> is the mouse button number:
  836.  *
  837.  *               0 - Left   Button
  838.  *               1 - Right  Button
  839.  *               2 - Middle Button [if applicable]
  840.  *
  841.  *    <nButPrs> is the number of times the specified button was pressed
  842.  *              since the last call to this routine. PASSED BY REFERENCE.
  843.  *    <nX> is the X position of the cursor when the last press occurred. 
  844.  *              PASSED BY REFERENCE.
  845.  *    <nY> is the Y position of the cursor when the last press occurred. 
  846.  *              PASSED BY REFERENCE.
  847.  *
  848.  * $RETURNS$
  849.  *    An integer representing the button status:
  850.  *
  851.  *               0 - no buttons pressed
  852.  *               1 - left button pressed
  853.  *               2 - right button pressed
  854.  *               3 - left and right pressed
  855.  *               4 - middle pressed
  856.  *               5 - left and middle pressed
  857.  *               6 - middle and right buttons pressed
  858.  *               7 - all 3 buttons pressed
  859.  * $DESCRIPTION$
  860.  *    Retrieves the mouse button status and the position of the cursor when
  861.  *    a button was last pressed. 
  862.  * $EXAMPLES$
  863.  *    IF Empty( FT_MBUTPRS(1) )
  864.  *       ? "No Item selected"
  865.  *    ENDIF
  866.  *  $SEEALSO$
  867.  *     FT_MBUTREL() FT_MDBLCLK()
  868.  * $END$
  869.  */
  870.  
  871. FUNCTION FT_MBUTPRS( nButton, nButPrs, nX, nY ) // get button press information
  872.  
  873.    aReg[AX] := 5               // set mouse function call 5
  874.    aReg[BX] := nButton          // pass parameter for left or right button
  875.    FT_INT86( 51, aReg )        // execute mouse interrupt
  876.    nButPrs := aReg[BX] // store updated press count
  877.    nX := aReg[DX]      // x-coordinate at last press
  878.    nY := aReg[CX]      // y-coordinate at last press
  879.  
  880. RETURN aReg[AX]                 // return button status
  881.  
  882.  
  883.  
  884. /*  $DOC$
  885.  *  $FUNCNAME$
  886.  *     FT_MBUTREL()
  887.  *  $CATEGORY$
  888.  *     Keyboard/Mouse
  889.  *  $ONELINER$
  890.  *     Get mouse button release information
  891.  *  $SYNTAX$
  892.  *     FT_MBUTREL( nButton [, @nButRel [, @nX [, @nY] ] ]) -> nBStat
  893.  *  $ARGUMENTS$
  894.  *     <nButton> is the mouse button number
  895.  *               0 - Left   Button
  896.  *               1 - Right  Button
  897.  *               2 - Middle Button [if applicable]
  898.  *
  899.  *    <nButRel> is the number of times the specified button was released
  900.  *              since the last call to this routine. PASSED BY REFERENCE.
  901.  *
  902.  *    <nX> is the X position of the cursor when the last release occurred.
  903.  *              PASSED BY REFERENCE.
  904.  *
  905.  *    <nY> is the Y position of the cursor when the last release occurred.
  906.  *              PASSED BY REFERENCE.
  907.  *  $RETURNS$
  908.  *     <nBStat>  - an integer representing button release status
  909.  *                 0 - None
  910.  *                 1 - Left
  911.  *                 2 - Right
  912.  *                 3 - Middle
  913.  *  $DESCRIPTION$
  914.  *     This function returns the release status of the mouse buttons and the
  915.  *     coordinates of the last release.
  916.  *  $EXAMPLES$
  917.  *     IF( FT_MBUTREL( 0 ) == 1 )
  918.  *        ? "Left button released"
  919.  *     ENDIF
  920.  *  $SEEALSO$
  921.  *     FT_MBUTPRS() FT_MDBLCLK()
  922.  *  $END$
  923.  */
  924.  
  925.  
  926.  
  927. FUNCTION FT_MBUTREL( nButton, nButRel, nX, nY ) // get button release information
  928.  
  929.    aReg[AX] := 6                // set mouse function call 6
  930.    aReg[BX] := nButton          // pass parameter for left or right button
  931.    FT_INT86( 51, aReg )        // execute mouse interrupt
  932.    nButRel := aReg[BX]  // store updated release count 
  933.    nX := aReg[DX]      // x-coordinate at last release
  934.    nY := aReg[CX]      // y-coordinate at last release
  935.  
  936. RETURN aReg[AX]                 // return button status
  937.  
  938.  
  939. /*
  940.  * $DOC$         
  941.  * $FUNCNAME$
  942.  *    FT_MDEFCRS()
  943.  * $CATEGORY$
  944.  *    Keyboard/Mouse
  945.  * $ONELINER$
  946.  *    Define the mouse cursor
  947.  * $SYNTAX$
  948.  *    FT_MDEFCRS( <nCrsType>, <nScrMask>, <nCrsMask> ) -> NIL
  949.  * $ARGUMENTS$
  950.  *    <nCrsType> is the cursor type. A value of 0 indicates the software cursor
  951.  *               (the default) and a value of 1 indicates the hardware cursor.
  952.  *
  953.  *    <nScrMask> is the screen mask for the software cursor or the first scan
  954.  *               line of the hardware cursor. See the description for more 
  955.  *               information.               
  956.  *
  957.  *    <nCrsMask> is the cursor mask for the software cursor of the last scan
  958.  *               line of the hardware cursor. See the description for more
  959.  *               information.
  960.  * $RETURNS$
  961.  *    NIL
  962.  * $DESCRIPTION$
  963.  *    In text mode the mouse cursor can either be a software generated or 
  964.  *    the actual hardware cursor. This routine allows one choose between them.
  965.  *    The software cursor is the default and its effect on the character it
  966.  *    covers is determined by the screen mask and the cursor mask. Both of
  967.  *    these masks are 16 bit values (which in Clipper are passed as standard
  968.  *    numerical values). The 16 bit masks are arranged in a manner identical
  969.  *    to the way information is stored for each character cell on the screen.
  970.  *    The low order 8 bits represent the actual character displayed while the
  971.  *    high order bits represent the display atributes such as blinking,
  972.  *    intensity and forground and background colors. The mask is represented in
  973.  *    the diagram below:
  974.  *
  975.  *    Bit:     │15    │14      12│11       │10       8│7       0│
  976.  *    Function:│blink │background│intensity│foreground│character│
  977.  *
  978.  *    Blinking and high intensity are on when the bit is 1. The background and
  979.  *    foreground indicate which colors are used for each. The software mouse
  980.  *    cursor uses these two values by taking the mask from the screen cell it 
  981.  *    is on and performing a logical AND on each bit with the screen mask 
  982.  *    value. The result is then logically XOR'ed with the cursor mask value.
  983.  *    Thus to keep the character the same but invert the foreground and
  984.  *    background colors the following values would be used:
  985.  *
  986.  *    Bit:     │15    │14      12│11       │10       8│7       0│
  987.  *    Function:│blink │background│intensity│foreground│character│
  988.  *    screen:  │  0   │   111    │    0    │   111    │11111111 │ =30719
  989.  *    cursor:  │  0   │   111    │    0    │   111    │00000000 │ =30464
  990.  *
  991.  *    The hardware cursor is the text cursor provided by the video board. One
  992.  *    specifies the range of scan lines which are on using <nScrMask> and
  993.  *    <nCrsMask>. The range of values is dependant upon the type of monitor.
  994.  *    The first scan line is 0.
  995.  * $END$
  996.  */
  997.  
  998. FUNCTION FT_MDEFCRS( nCurType, nScrMask, nCurMask )   // define text cursor type and masks
  999.  
  1000.    aReg[AX] = 10          // set mouse function call 10
  1001.    aReg[BX] = nCurType   // load cursor type parameter
  1002.    aReg[CX] = nScrMask   // load screen mask value
  1003.    aReg[DX] = nCurMask   // load cursor mask value
  1004.    FT_INT86( 51, aReg ) // execute mouse interrupt
  1005.  
  1006. RETURN NIL              // no function output
  1007.  
  1008.  
  1009. /*
  1010.  * $DOC$         
  1011.  * $FUNCNAME$
  1012.  *    FT_MMICKEYS()
  1013.  * $CATEGORY$
  1014.  *    Keyboard/Mouse
  1015.  * $ONELINER$
  1016.  *    Get mickeys
  1017.  * $SYNTAX$
  1018.  *    FT_MMICKEYS( @<nX>, @<nY> ) -> NIL
  1019.  * $ARGUMENTS$
  1020.  *    <nX> is a variable that will receive the vertical mickey count.
  1021.  *
  1022.  *    <nY> is a variable that will receive the horizontal mickey count.
  1023.  * $RETURNS$
  1024.  *    NIL
  1025.  * $DESCRIPTION$
  1026.  *    <nX> and <nY> must be passed by reference to receive
  1027.  *    the mouse position in Mickeys.
  1028.  * $EXAMPLES$
  1029.  *    FT_MMICKEYS( @nX, @nY )
  1030.  *    ? nX
  1031.  *    ? nY
  1032.  * $END$
  1033.  */
  1034.  
  1035. FUNCTION FT_MMICKEYS( nX, nY ) // read mouse motion counters
  1036.  
  1037.    aReg[AX] = 11                // set mouse function call 11
  1038.    FT_INT86( 51, aReg )        // execute mouse interrupt
  1039.    nX := aReg[CX]               // store horizontal motion units
  1040.    nY := aReg[DX]               // store vertical motion units
  1041.  
  1042. RETURN NIL                     // no function output
  1043.  
  1044.  
  1045. /*
  1046.  * $DOC$         
  1047.  * $FUNCNAME$
  1048.  *    FT_MDBLCLK()
  1049.  * $CATEGORY$
  1050.  *    Keyboard/Mouse
  1051.  * $ONELINER$
  1052.  *    Return true if a double click was detected
  1053.  * $SYNTAX$
  1054.  *    FT_MDBLCLK( [ <nClick> [, <nButton> [, <nInterval> [, <nRow> [, <nCol>;
  1055.  *                [, <nTime> ] ] ] ] ] ] ) -> lIsDoubleClk
  1056.  * $ARGUMENTS$
  1057.  *    <nClick> is a numeric value.  If it is zero FT_MDBLCLK() will not 
  1058.  *             check for the first press but rather will simply wait the
  1059.  *             specified period for a single press. This is useful if this
  1060.  *             routine is called from one which in turn responded to a button
  1061.  *             press. If it is not present or not equal to 0, then FT_MDBLCLK()
  1062.  *             will wait for two presses of the specified button.
  1063.  *
  1064.  *    <nButton> is the mouse button number
  1065.  *               0 - Left   Button
  1066.  *               1 - Right  Button
  1067.  *               2 - Middle Button [if applicable]
  1068.  *
  1069.  *    <nInterval> is the interval to wait for the first click if requested
  1070.  *           and the time to wait for the second. If not present then defaults
  1071.  *           to 0.5 second.
  1072.  *
  1073.  *    <nRow> is the row number for the mouse cursor location for a double click
  1074.  *           to be valid. If not present then the current position is taken as
  1075.  *           the valid location.
  1076.  *
  1077.  *    <nCol> is the column number for the mouse cursor location for a double
  1078.  *           click to be valid. If not present, then the current position is
  1079.  *           taken as the valid location.
  1080.  *
  1081.  *    <nTime> is an optional start time for the waiting period for the first
  1082.  *           click (of either one or two requested). If not given then the
  1083.  *           time is set at entry into this routine. This is useful when this
  1084.  *           routine is called from another routine which was called in 
  1085.  *           response to a mouse click but needs to know if a double click
  1086.  *           has occurred
  1087.  * $RETURNS$
  1088.  *    .T. if a double click was detected.
  1089.  * $DESCRIPTION$
  1090.  *    This is a mouse meta function that checks for the presence
  1091.  *    of a double click.
  1092.  * $EXAMPLES$
  1093.  *   IF FT_MISREGION( 10, 10, 11, 20 ) .AND.;
  1094.  *      FT_MDBLCLK(0,1,,FT_MGETX(),FT_MGETY())  && double click, right button
  1095.  *                                              && at current location with
  1096.  *                                              && default interval
  1097.  *
  1098.  *         MnuItem1()
  1099.  *   ENDIF
  1100.  *  $SEEALSO$
  1101.  *     FT_MBUTPRS() FT_MBUTREL()
  1102.  * $END$
  1103.  */
  1104.  
  1105. FUNCTION FT_MDBLCLK( nClick, nButton, nInterval, nRow, nCol, nStart )
  1106.  
  1107. LOCAL nVert, nHorz  // local row and col coordinates
  1108. LOCAL lDouble:=.F.  // double click actually occurred
  1109. LOCAL lDone          // loop flag
  1110. LOCAL nPrs           // number of presses which occurred
  1111.  
  1112. * Initialize any empty arguments
  1113.  
  1114.    if nClick=NIL
  1115.       nClick=1
  1116.    endif
  1117.  
  1118.    if nButton=NIL
  1119.         nButton=0
  1120.    endif
  1121.  
  1122.    if nRow=NIL
  1123.        nRow=FT_MGETX()
  1124.    endif
  1125.  
  1126.    if nCol=NIL
  1127.        nCol=FT_MGETY()
  1128.    endif
  1129.  
  1130.    if nInterval=NIL
  1131.        nInterval=0.5
  1132.    endif
  1133.  
  1134.    if nStart=NIL
  1135.        nStart=seconds()
  1136.    endif
  1137.  
  1138.    nVert=nRow
  1139.    nHorz=nCol
  1140.    lDouble:=lDone:=nClick==0
  1141.    
  1142.    // Wait for first press if requested
  1143.  
  1144.    do while !lDone
  1145.  
  1146.            FT_MBUTPRS( nButton, @nPrs, @nVert, @nHorz )
  1147.            nVert=INT(nVert/8)
  1148.            nHorz=INT(nHorz/8)
  1149.  
  1150.            lDouble=(nPrs>0)
  1151.            ldone= seconds() - nStart >= nInterval .or. lDouble
  1152.            
  1153.    enddo
  1154.  
  1155.    // if we have not moved then keep the preliminary double click setting
  1156.  
  1157.    lDouble=lDouble.and.(nVert=nRow.and.nHorz=nCol)
  1158.  
  1159.    // change start time if we waited for first click. nInterval is the
  1160.    // maximum time between clicks not the total time for two clicks if 
  1161.    // requested.
  1162.  
  1163.    if nClick>0
  1164.       nStart=seconds()
  1165.    endif
  1166.  
  1167.    // If we have fulfilled all of the requirements then wait for second click
  1168.  
  1169.    if lDouble
  1170.  
  1171.       lDouble:=lDone:=.F.
  1172.       
  1173.       do while !lDone
  1174.  
  1175.            FT_MBUTPRS( nButton, @nPrs, @nVert, @nHorz )
  1176.            nVert=INT(nVert/8)
  1177.            nHorz=INT(nHorz/8)
  1178.  
  1179.            lDouble=(nPrs>0)
  1180.            lDone= seconds() - nStart >= nInterval .or. lDouble
  1181.            
  1182.       enddo
  1183.  
  1184.   // make sure we haven't moved 
  1185.  
  1186.       lDouble=lDouble.and.(nVert=nRow.and.nHorz=nCol)
  1187.  
  1188.    endif
  1189.  
  1190.  
  1191. RETURN lDouble
  1192.  
  1193. /*
  1194.  * $DOC$         
  1195.  * $FUNCNAME$
  1196.  *    FT_MCONOFF()
  1197.  * $CATEGORY$
  1198.  *    Keyboard/Mouse
  1199.  * $ONELINER$
  1200.  *    Turn mouse cursur off if in specified region
  1201.  * $SYNTAX$
  1202.  *    FT_MCONOFF( <nTop>, <nLeft>, <nBottom>, <nRight> )
  1203.  * $ARGUMENTS$
  1204.  *    <nTop>, <nLeft> <nBottom> <nRight> are the four corners of the
  1205.  *          screen region in row and column coordinates.
  1206.  * $RETURNS$
  1207.  *    NIL
  1208.  * $DESCRIPTION$
  1209.  *    This function tells the mouse driver to hide the cursor if it is in
  1210.  *    the given region. The driver hides the cursor by decrementing the cursor
  1211.  *    flag. A call to FT_MSHOWCRS is required to turn the cursor back on.
  1212.  *    Calling FT_MSHOWCRS also disables this function.
  1213.  *
  1214.  *    See FT_MSHOWCRS for a discussion of the cursor display flag.
  1215.  * $EXAMPLES$
  1216.  *    FT_MCONOFF( 10, 10, 11, 20 )
  1217.  *  $SEEALSO$
  1218.  *     FT_MSHOWCRS() FT_MHIDECRS() FT_MXLIMIT() FT_MYLIMIT() FT_MINREGION()
  1219.  * $END$
  1220.  */
  1221.  
  1222. FUNCTION FT_MCONOFF( nTop, nLeft, nBottom, nRight )
  1223.  
  1224. * Fill the registers
  1225.  
  1226.    aReg[AX]:=16
  1227.    aReg[DX]:=nTop*8
  1228.    aReg[CX]:=nLeft*8
  1229.    aReg[DI]:=nBottom*8
  1230.    aReg[SI]:=nRight*8
  1231.    FT_INT86( 51, aReg )        // execute mouse interrupt
  1232.  
  1233. RETURN NIL
  1234.  
  1235. /*
  1236.  * $DOC$         
  1237.  * $FUNCNAME$
  1238.  *    FT_MINREGION()
  1239.  * $CATEGORY$
  1240.  *    Keyboard/Mouse
  1241.  * $ONELINER$
  1242.  *    Test if the mouse cursor is in the passed region
  1243.  * $SYNTAX$
  1244.  *    FT_MINREGION( <nT>, <nL>, <nB>, <nR> ) -> lInRegion
  1245.  * $ARGUMENTS$
  1246.  *    <nT>, <nL> <nB> <nR> are the four corners of the screen region.
  1247.  * $RETURNS$
  1248.  *    .T. if mouse is in specified region.
  1249.  * $DESCRIPTION$
  1250.  *    This function will check to see if the mouse cursor is
  1251.  *    within the confines of the specified region.
  1252.  * $EXAMPLES$
  1253.  *    IF FT_MINREGION( 10, 10, 11, 20 )
  1254.  *      nChoice := 1
  1255.  *    ENDIF
  1256.  *  $SEEALSO$
  1257.  *     FT_MXLIMIT() FT_MYLIMIT() FT_MINREGION()
  1258.  * $END$
  1259.  */
  1260.  
  1261. FUNCTION FT_MINREGION( nTR, nLC, nBR, nRC )
  1262. RETURN ( FT_MGETX() >= nTR .and. FT_MGETX() <= nBR .and. ;
  1263.          FT_MGETY() >= nLC .and. FT_MGETY() <= nRC )
  1264.  
  1265.  
  1266. /*
  1267.  * $DOC$         
  1268.  * $FUNCNAME$
  1269.  *    FT_MSETSENS()
  1270.  * $CATEGORY$
  1271.  *    Keyboard/Mouse
  1272.  * $ONELINER$
  1273.  *    Set the mouse sensitivity parameters
  1274.  * $SYNTAX$
  1275.  *    FT_MSETSENS( <nHoriz>, <nVert>, <nDouble> ) -> NIL
  1276.  * $ARGUMENTS$
  1277.  *    <nHoriz>  is the sensitivity of the mouse on the horizontal axis. This
  1278.  *              value is the integer percentage of highest sensitivity and 
  1279.  *              thus has a range of 1 to 100. The default value is 50 and at
  1280.  *              this setting about 3.2 inches of mouse movement will move 
  1281.  *              the mouse cursor across the screen. If NIL, the current 
  1282.  *              value is used.
  1283.  *    <nVert>   is the relative sensitivity of the mouse on the vertical axis.
  1284.  *              The value is an integer percentage of the highest sensitivity
  1285.  *              and thus has a range of 1 to 100. The default value is 50 and
  1286.  *              requires about 2 inches of mouse movement will move from top 
  1287.  *              to bottom of the screen.If NIL, the current value is used.
  1288.  *    <nDouble> is the relative sensitivity of the mouse to doubling the ratio
  1289.  *              of cursor movement to mouse movement. The default
  1290.  *              value is 50. If NIL, the current value is used.
  1291.  * $RETURNS$
  1292.  *    NIL
  1293.  * $DESCRIPTION$
  1294.  *    This function allows one to control the mouse movement sensitivity. The
  1295.  *    first two arguments control the amount of movement necessary to move
  1296.  *    the cursor a given amount. The values are the percentage of full
  1297.  *    sensitivity and the default values after installing the mouse driver
  1298.  *    is 50 which represents approximately 3.2 inches of horizontal
  1299.  *    and 2 inches of vertical mouse movement to cover the entire screen. 
  1300.  *    A value of 100 requires about 0.9 inches of horizontal mouse movement to
  1301.  *    cover the screen from one side to the other.
  1302.  *
  1303.  *    The third argument changes the threshold above which the mouse moves at
  1304.  *    twice the normal speed. The value is a percentage of full sensitivity
  1305.  *    with the default (50) providing doubling at 64 mickeys per second.
  1306.  *
  1307.  *    NOTE: These values are NOT restored after resetting the mouse driver/
  1308.  *    hardware. A well behaved application should reset them to the
  1309.  *    original value upon exiting.
  1310.  *
  1311.  *    NOTE: The above description is counter to all of the documentation
  1312.  *    I have available. However, it does not work the way it is documented
  1313.  *    with Microsoft drivers versions 6.16, 6.24, 7.04 and 8.20. The above 
  1314.  *    movement values are documented to be the number of mickeys per 8 
  1315.  *    pixels and the double speed value as the number mickeys per second 
  1316.  *    required to double the speed. Each of these values should range from 1 
  1317.  *    to 32K but the driver forces a maximum of 100. Also the documentation
  1318.  *    states that resetting the mouse will reset these values. This is not
  1319.  *    the case.
  1320.  *
  1321.  * 
  1322.  * $EXAMPLES$
  1323.  *    FT_MSETSENS( 75,75,50 )     // a little less mouse movement necessary.
  1324.  *  $SEEALSO$
  1325.  *    FT_MGETSENS()
  1326.  * $END$
  1327.  */
  1328.  
  1329. FUNCTION FT_MSETSENS(nHoriz, nVert, nDouble)
  1330. LOCAL nCurHoriz, nCurVert, nCurDouble
  1331.  
  1332. // Get current values
  1333.  
  1334. FT_MGETSENS(@nCurHoriz, @nCurVert, @nCurDouble)
  1335.  
  1336. // Set defaults if necessary
  1337.  
  1338. IF VALTYPE(nHoriz)!="N"
  1339.     nHoriz=nCurHoriz
  1340. ENDIF
  1341.  
  1342. IF VALTYPE(nVert)!="N"
  1343.     nVert=nCurVert
  1344. ENDIF
  1345.  
  1346. IF VALTYPE(nDouble)!="N"
  1347.     nDouble=nCurDouble
  1348. ENDIF
  1349.  
  1350. * Fill the registers
  1351.  
  1352. aReg[AX]=26
  1353. aReg[BX]=INT(nHoriz)
  1354. aReg[CX]=INT(nVert)
  1355. aReg[DX]=INT(nDouble)
  1356.  
  1357. * Execute interupt
  1358.  
  1359. FT_INT86( 51, aReg )        // execute mouse interrupt
  1360.  
  1361. RETURN NIL
  1362.  
  1363.  
  1364. /*
  1365.  * $DOC$         
  1366.  * $FUNCNAME$
  1367.  *    FT_MGETSENS()
  1368.  * $CATEGORY$
  1369.  *    Keyboard/Mouse
  1370.  * $ONELINER$
  1371.  *    Get the mouse sensitivity parameters
  1372.  * $SYNTAX$
  1373.  *    FT_MGETSENS( <@nHoriz>, <@nVert>, <@nDouble> ) -> NIL
  1374.  * $ARGUMENTS$
  1375.  *    <nHoriz>  is the percentage of maximum horizontal sensitivity. PASSED 
  1376.  *              BY REFERENCE.
  1377.  *    <nVert>   is the percentage of maximum vertical sensitivity. PASSED BY
  1378.  *              REFERENCE.
  1379.  *    <nDouble> is the percentage of maximum sensitivity for doubling the
  1380.  *              mouse cursor's speed on the screen. PASSED BY REFERENCE.
  1381.  * $RETURNS$
  1382.  *    NIL
  1383.  * $DESCRIPTION$
  1384.  *    This function returns the current values of the mouse movement 
  1385.  *    sensitivity parameters. The first two arguments control the amount of 
  1386.  *    movement necessary to move the cursor a given amount. The third argument 
  1387.  *    determines the threshold above which the mouse moves at twice the normal 
  1388.  *    speed. For further discussion of these values see FT_MSETSENS()
  1389.  * $EXAMPLES$
  1390.  *    FT_MGETSENS( @nHoriz, @nVert, @nDouble )
  1391.  *  $SEEALSO$
  1392.  *    FT_MSETSENS()
  1393.  * $END$
  1394.  */
  1395.  
  1396. FUNCTION FT_MGETSENS(nHoriz, nVert, nDouble)
  1397.  
  1398. * Fill the register
  1399.  
  1400. aReg[AX]=27
  1401.  
  1402. * Execute interupt
  1403.  
  1404. FT_INT86( 51, aReg )        // execute mouse interrupt
  1405.  
  1406.  
  1407. // Set the return values
  1408.  
  1409. nHoriz = aReg[BX]
  1410. nVert  = aReg[CX]
  1411. nDouble= aReg[DX]
  1412.  
  1413. RETURN NIL
  1414.  
  1415.  
  1416. /*
  1417.  * $DOC$         
  1418.  * $FUNCNAME$
  1419.  *    FT_MVERSION()
  1420.  * $CATEGORY$
  1421.  *    Keyboard/Mouse
  1422.  * $ONELINER$
  1423.  *    Get the mouse driver version
  1424.  * $SYNTAX$
  1425.  *    FT_MVERSION( <@nMinor>, <@nType>, <@nIRQ>  ) -> <nMajor>
  1426.  * $ARGUMENTS$
  1427.  *    <nMinor>  is the Minor version number. PASSED BY REFERENCE.
  1428.  *    <nType>   is the Mouse type. PASSED BY REFERENCE.
  1429.  *                  1 = Bus Mouse
  1430.  *                  2 = Serial Mouse
  1431.  *                  3 = InPort Mouse
  1432.  *                  4 = PS/2 Mouse
  1433.  *                  5 = HP Mouse
  1434.  *    <nIRQ>    is the IRQ number used for the mouse. PASSED BY REFERENCE.
  1435.  *                  0 = PS/2
  1436.  *                  2,3,4,5 or 7 = IRQ number
  1437.  * $RETURNS$
  1438.  *    <nMajor> which is the major version number of the mouse driver.
  1439.  * $DESCRIPTION$
  1440.  *    This function returns the current values of the mouse driver version
  1441.  *    number and type. The major version would be 6 and the minor version
  1442.  *    would be 10 if the driver were version 6.10. The mouse type and IRQ
  1443.  *    numbers are also returned.
  1444.  *
  1445.  *    NOTE: It appears that the values reported when one starts the mouse
  1446.  *    driver actually have the minor version in hexadecimal! Thus on bootup
  1447.  *    my screen showed 6.24 but this routine returned 30 for the minor version
  1448.  *    number!
  1449.  * $EXAMPLES$
  1450.  *    nMajor=FT_MVERSION( @nMinor )
  1451.  *    IF (nMajor+nMinor/100)<7.2 
  1452.  *         ? "Sorry mouse driver version too old"
  1453.  *         RETURN
  1454.  *    ENDIF
  1455.  *  $SEEALSO$
  1456.  *    FT_MSETSENS()
  1457.  * $END$
  1458.  */
  1459.  
  1460. FUNCTION FT_MVERSION(nMinor, nType, nIRQ)
  1461.  
  1462. // Set up register
  1463.  
  1464. aReg[AX] = 36
  1465.  
  1466. // Call interupt
  1467.  
  1468. FT_INT86( 51, aReg)
  1469.  
  1470. // decode out of half registers
  1471.  
  1472. nMinor=LowByte(aReg[BX])
  1473. nType=HighByte(aReg[CX])
  1474. nIRQ=LowByte(aReg[CX])
  1475.  
  1476. // Return
  1477.  
  1478. RETURN HighByte(aReg[BX])
  1479.  
  1480.  
  1481. /*
  1482.  * $DOC$         
  1483.  * $FUNCNAME$
  1484.  *    FT_MSETPAGE()
  1485.  * $CATEGORY$
  1486.  *    Keyboard/Mouse
  1487.  * $ONELINER$
  1488.  *    Set the display page for the mouse pointer
  1489.  * $SYNTAX$
  1490.  *    FT_MSETPAGE( <@nPage> ) -> NIL
  1491.  * $ARGUMENTS$
  1492.  *    <nPage>  is the desired display page.
  1493.  * $RETURNS$
  1494.  *    NIL
  1495.  * $DESCRIPTION$
  1496.  *    This function sets the display page for the mouse cursor. The valid
  1497.  *    values of nPage is dependent upon the display mode. See FT_SETVPG()
  1498.  *    for changing the current video page
  1499.  * $EXAMPLES$
  1500.  *    FT_MSETPAGE( 1 )  // Sets the mouse cursor to page 1
  1501.  *  $SEEALSO$
  1502.  *    FT_MGETPAGE()
  1503.  * $END$
  1504.  */
  1505.  
  1506. FUNCTION FT_MSETPAGE(nPage)
  1507.  
  1508. // Set up register
  1509.  
  1510. aReg[AX] = 29
  1511. aReg[BX]=nPage
  1512.  
  1513. // Call interupt
  1514.  
  1515. FT_INT86( 51, aReg)
  1516.  
  1517. RETURN NIL
  1518.  
  1519. /*
  1520.  * $DOC$         
  1521.  * $FUNCNAME$
  1522.  *    FT_MGETPAGE()
  1523.  * $CATEGORY$
  1524.  *    Keyboard/Mouse
  1525.  * $ONELINER$
  1526.  *    Get the display page for the mouse pointer
  1527.  * $SYNTAX$
  1528.  *    FT_MGETPAGE() -> <nPage>
  1529.  * $ARGUMENTS$
  1530.  *    None
  1531.  * $RETURNS$
  1532.  *    <nPage>  is the display page on which the mouse is currently being
  1533.  *         displayed
  1534.  * $DESCRIPTION$
  1535.  *    This function gets the display page for the mouse cursor. The valid
  1536.  *    values of nPage is dependent upon the display mode. See FT_SETVPG()
  1537.  *    for changing the current video page
  1538.  * $EXAMPLES$
  1539.  *    nPage = FT_MGETPAGE( )  // Gets the mouse cursor display page 
  1540.  *  $SEEALSO$
  1541.  *    FT_MSETPAGE()
  1542.  * $END$
  1543.  */
  1544.  
  1545. FUNCTION FT_MGETPAGE(nPage)
  1546.  
  1547. // Set up register
  1548.  
  1549. aReg[AX] = 30
  1550.  
  1551. // Call interupt
  1552.  
  1553. FT_INT86( 51, aReg)
  1554.  
  1555. RETURN aReg[BX]
  1556.  
  1557.