                        JPmouse.zip, Version 1.0

        Program to manage the dBASE IV, Version 1.5, mouse.
*------------------------------------------------------------------------
*-- Programmer    : Jay Parsons, CIS 70160,340
*-- Date          : May 25, 1992
*-- Notes         : A .bin file for the dBASE IV 1.5 mouse.
*-- Revisions     : None
*-- Usage         : See below.
*-- Parameters    : a single character among six; see below.
*------------------------------------------------------------------------

        This ZIP file contains the following files:

                JPMOUSE.BIN, a dBASE IV 1.5 .bin to manage the mouse.
                JPMOUSE.ASM, its source code.
                README, this file.

        If you simply want to use the mouse in dBASE IV, Version 1.5,
you don't need any of this.  This program is intended for those developers
who wish to control the use of the mouse by their users.

                        Disclaimer

        The concepts used in this program were picked up through hurried
experimentation and skimming the mostly unhelpful "Microsoft Mouse
Programmer's Reference", Second Edition, Microsoft Press, 1991.  If the
author's understanding is incorrect, which has happened, so is the
program.  Advice of any errors in understanding, as well as of any bugs
in the program, will be appreciated.
                                    
                        Use in general

        SETMOUSE.BIN must be loaded by the dBASE command LOAD Setmouse.
Thereafter, it may be called with any of five one-character arguments that
fall into three groups:

                   '?' to check for and reset mouse.  Does NOT show it

                   '+' to enable driver and show(?) mouse cursor
                   '-' to disable driver and hide mouse cursor

                   'S' to show(?) cursor only
                   'H' to hide cursor only

        Example:    LOAD JPmouse
                    Ismouse = ( call("JPmouse","?") = 'T' )

        If no argument is given, the routine does nothing and returns
nothing.  If an argument of at least one character is given, the routine
does as follows:

        If the character is not in the set of permissible arguments ( lower-
case is acceptable for letters ), it does nothing and returns 'F'.

        If the argument is '?', it checks for a mouse and enables it.
It should not turn the mouse on, but it will be on if the .bin has been
called from the dot prompt.  If called this way, the .bin returns either
'T' if a mouse driver is found or 'F'.

        In all other cases, it acts as though there is a mouse whether there
is or not and returns 'T'.

        NOTE: As always in dBASE, a .bin can return a value only
                1) as the result of the call() function; or
                2) in a variable passed as an argument.
        Consequently, do not use 'CALL JPmouse WITH "?"'.  The .bin
will report the status to the argument buffer in which dBASE passed the
character literal "?", but dBASE will have no way to access it.
Use the call() function instead of the CALL command, or place the argument
in a variable and CALL WITH that.

                        Anatomy of Mice

        Why all the complication?  Because dBASE itself turns the mouse on
when issuing the dot prompt, because the mouse calls work in complex ways,
and because turning the mouse on when it is on leaves immobile cursors,
"mouse droppings", on the screen.

        The designers of the mouse software considered the possibility that
a subroutine or function might want to hide the mouse cursor while doing
video output, but that the mouse cursor might already have been hidden by
some higher-level routine.  Accordingly, the mouse is designed so that
any call to turn it off will do so, but a call to turn it on will take
effect only if it was on before the last call to turn it off.  A counter
that I call the "showmouse" counter is kept.  Turning the mouse on increases
its value; turning it off decreases it.  The mouse comes on only when the
showmouse counter is zero, after which no more calls to turn it on change
the counter, although they do leave mouse turds.  A call to reset the mouse
sets the counter to -1, hidden but ready to be shown by the next call.

                        Mouse driver functions

        Microsoft decreed that the mouse driver should inhabit interrupt
33h (51) and respond in fixed ways to calls to that interrupt.  While
numerous functions are provided that this program does not use, these are
the interrupt 33h functions it does use:

                Function 0      Reset mouse
                Function 1      Show mouse
                Function 2      Hide mouse
                Function 1Fh    Disable mouse
                Function 20h    Enable mouse

        The reset function, Function 0, cleans up everything, returns the
mouse to screen center, enables it, and sets the showmouse counter to -1.

        The show function increments the showmouse counter.  If it was -1,
it becomes 0 and the mouse cursor appears.  If it was 0, mouse turds appear.

        The hide function decrements the showmouse counter, always hiding
the mouse cursor since the counter is never greater than 0.

        The disable function stops the mouse driver from tracking what the
mouse does, and the enable function starts it tracking again.  Neither has
a direct effect on the mouse cursor.

        The arguments to JPmouse call these functions as follows:

                '?' calls function 0.

                '+' calls function 20h, then function 1.
                '-' calls function 1Fh, then function 2.

                'S' calls function 1 only.
                'H' calls function 2 only.

                   Belt, Suspenders and Velcro too

        The "?" call to the .bin uses the technique recommended by
Microsoft to detect the presence of a mouse driver.  This is a totally
stupid technique.  It first looks for "00 00 00 00" as the vector for
int 33h, the mouse interrupt.  To be sure, if this vector were null
there would be a serious problem, because the processor would jump to
location 0000:0000 and try to execute as code the address found there.
A crash would almost surely result.  However, one of the first things
the computer does on power up is place a jump to an IRET in each interrupt
vector so that calling one that is not used will not be fatal.  If there
is in fact a set of four nulls as the int 33h vector, there's a lot more
wrong than the absence of a mouse and it is unlikely that this defense
will salvage the situation.

        The presence of an IRET at the location pointed to by the int 33h
vector does show there is no mouse driver.  On the other hand, calling one
of the int 33h functions such as 0 to reset the mouse will, if the vector
points to an IRET, return with nothing changed, after which the calling
program will know there is no driver.  Accordingly, checking for an IRET
is essentially a waste of time.

        If you have an assembler, be brave and remove this garbage from
the program.

                            dBASE Programming

        In programs, it is often desirable to check for a mouse and turn it
on if it exists with one operation.  From the dot prompt, this is disastrous
because after the program turns on the mouse, so will dBASE, leaving mouse
turds.  Consequently, this program is written so that when the bin is called
with "?", it should not set the mouse on.

        Unfortunately, the state of the mouse is hard to predict.  I think,
but do not know for sure, that calling this bin with "?", then with "-",
and finally with "+" will always turn on the mouse and its cursor without
leaving mouse droppings.  Assistance of any volunteer "beta testers" in
figuring out how to do this properly is welcomed.

        If the mouse is disabled with '-', enable it again with '+' and
the cursor will reappear in the same place it disappeared from.  If you want
to start it over in the center of the screen after a call with '-', call
with '?'.  Don't, however, call with an '?' in a function or other
subroutine if a higher-level routine may have itself turned the mouse off.
To avoid turning it on inappropriately, use only the '+' and '-', or 'H'
and 'S', calls in such a case.

        You should be able to keep track of whether the mouse is on or
off with a program variable, remembering that dBASE will reset it and
turn it on after a RUN command.  You may call JPmouse with '+' and '-' to
switch from one state to the other.  However, if you lose track, calling
with '+' may leave mouse turds.  If in doubt, call with '?' to reset it,
then with "-", before calling with '+'.

        Why then the 'H' and 'S' calls?  These will not often be needed.
They simply allow hiding the mouse cursor quickly and showing it again
when it is required only to hide it for an instant, as during a screen
repaint.  If the mouse is to be off while dBASE is accepting actions from
the user, use '-' instead so the user's clicks will be ignored.

        When leaving a program, if the mouse is off, be sure to turn it
on with a call with "+".  If you don't, dBASE will get the mouse in an
unknown state and mouse turds or just absence of the mouse when wanted
may ensue.

                        Summary

                Check for mouse with "?"
                Turn off with "-".
                Turn on, after "?" and only if off, with "+".
                If you lose track of the showmouse counter, call with "?"
                   then "+" to prevent mouse droppings.
                Before leaving a program, turn it on with "+" if off.

        In a procedure or function:

                Do not use "?" if the mouse may already have been
                   turned off for good reason outside.  Use "-" to hide
                   it and "+" to restore it to its condition before "-".

        For momentary hide and reshow, where disabling the mouse driver
           is not needed to keep dBASE from mistaking user fiddling for
           useful input:
                Use "H" and "S" instead of "-" and "+" if the very slight
                   increase in speed of execution matters.
                If you've lost track of the showmouse counter, use "?"
                   to reset it to -1, then use "S" to show the cursor.

*-----------------------------------------------------------------------
        This program is not copyrighted.  Use it as you wish, no charge.
However, I'll appreciate your leaving my name and address with it so
that you or others can report bugs or other problems.

Bernardsville, NJ 07924                            Jay Parsons
May 25, 1992                                       CIS 70160,340

