MyMouse		Improved mouse control by new service routines.
ver 1.60	Copyright (c) 1993 by Matthias Kppe.

-----------------------------------------------------------------------------

1  General Information
----------------------

MyMouse is a Turbo Pascal unit and is used for improved mouse control in
Pascal programs.
The MyMouse unit defines new routines for mouse cursor drawing. Therefore,
it provides a lot of new features:

 1  Support of larger mouse cursors.

      Conventional mouse drivers only support mouse cursors of 16 x 16 pixels
      size. The standard size of MyMouse cursors is 16 x 32 pixels, but even
      64 x 64 is no problem to MyMouse.

 2  Supply of several hard-coded mouse cursors.

      * mouse arrow in Windows size
      * hour glass
      * diverse crosses

 3  Flexible support of user-defined mouse cursors.

      User-defined cursors can very easily be applied with MyMouse.

 4  Support of automatical cursor adaption to GUI elements.

      MyMouse supports the automatical adaption of the mouse cursor moving
      over certain screen areas (e.g. windows).

 5  Support of cursor colors.

      Conventional mouse cursors only support white mouse drivers. With
      MyMouse, you won't have this restriction.

 6  SuperVGA & VESA support (800 x 600 x 16 and all 256-color modes).

      Hardly any DOS mouse driver supports the high-definition graphics modes
      of SuperVGA adaptor cards. MyMouse makes use of VESA, and supports
      any adaptor card that provides this protocol.

 7  Support of user-defined mouse service routines.

      With this facility, you can easily carry out any special idea for
      mouse cursor drawing.

 8  Co-operation with Borland Graphics Interface (BGI).

      Though MyMouse directly accesses the adaptor card for optimal
      performance, it is 100% compatible with BGI.

 9  Effective anti-flickering logic.

      MyMouse now provides an anti-flickering logic, which creates
      more comfort.

MyMouse provides efficient routines for screen region/page control.

10  Mouse area support.

      With MyMouse, you can easily lock the mouse into a box.

11  Mouse page support.

      With MyMouse, the cursor can appear on the second screen page.

12  Critical area/page support.

      With MyMouse, you can determine the screen region/page graphical
      operations work on. The mouse is only hidden if present there.

The MyMouse unit co-operates closely with the Turbo Vision Drivers unit.
Therefore, it achieves very much compatibility.

13  Generation of Drivers-compatible mouse events.

      The GetMouseEvent procedure generates events, which are completely
      compatible with the Drivers unit. By that, existing programs need
      not be modified in any way.

14  Generation of timer events.

      The GetTimerEvent procedure generates a new event class (evTimer) if
      a timer interrupt has happened since last call, i.e. 1/18.2 sec have
      passed.

15  Compact code by use of Drivers functions.

      MyMouse puts events into Drivers' event queue and uses many of its
      variables.

16  Use of Drivers parameters.

      You can still use the MouseReverse, DoubleDelay, and RepeatDelay
      variables.

17  DoubleSpeedTreshold adjustment.

      With MyMouse, you can set this value via a pascal procedure.

MyMouse co-operates in its driver mode with all mouse types. Microsoft and
Mouse Systems mice are DIRECTLY (without need of any driver) supported.
Ports, interrupt requests, and modes are automatically set.


2  Procedures and functions
---------------------------

procedure SetMouseMode(AMode: Word);

  This procedure sets the operating mode of the mouse. It is to be called
  before InitMyMouse. In following table the supported modes are given.

  mmDriver	The mouse driver handles the mouse's signals, and the
		Drivers unit generates the mouse events. MyMouse places
		a service routine between driver and Drivers, which processes
		the co-ordinates and draws the cursor.
		NOTE: In this mode, MyMouse co-operates with all mice. This
		      mode is default.
  mmMicro	The Drivers unit generates the mouse events, but the mouse's
		signals are directly handled by MyMouse's service routine.
		The connected mouse must be Microsoft serial.
  mmSystem	The Drivers unit generates the mouse events, but the mouse's
		signals are directly handled by MyMouse's service routine.
		The connected mouse must be Mouse Systems.
  mmAuto	The Drivers unit generates the mouse events, but the mouse's
		signals are directly handled by MyMouse's service routine.
		MyMouse determines by a driver call whether Microsoft
		serial or Mouse Systems is connected.

  In the three direct modes you may specify the port the mouse is connected
  to. Please add one of the following constants to the Mode identifier.

  mmPortAuto	Determines by a driver call which of the serial ports the
		mouse is connected to.
  mmPort1       Informs MyMouse that the mouse is connected to COM1.
  mmPort2	Informs MyMouse that the mouse is connected to COM2.

  In these modes, you can also specify the interrupt requests used by the
  mouse.

  mmIRQAuto	Determines by a driver call which interrupt request is used.
  mmIRQ(n)      Informs MyMouse that the mouse uses the interrupt request (n).

  In addition to these modes, you can set the following flags:

  mmNoClk	Disables the anti-flickering logic. MyMouse normally hooks
		the vertical retrace and fast timer interrupts in order to
		get the anti-flickering timing facility. This may cause
		problems under debugging circumstances.

procedure InitMyMouse;

  This procedure initializes MyMouse. Graphics needs not be initialized
  when calling InitMyMouse. MyMouse will wait for messages from
  Gr.InitGraphics and activate itself.

  If InitEvents has not been called yet, this is done by MyMouse. The
  driver's mouse cursor is hidden, and MyMouse's cursor is shown.

  The mouse mode is to be set BEFORE the InitMyMouse call. After this call,
  SetMouseMode is without any function.

  Call InitMyMouse before VgaMem's routine InitVgaMan. The latter one will
  allocate the whole VGA rest memory for its own use. MyMouse also needs a
  small part of this memory.

procedure DoneMyMouse;

  This procedure de-initializes MyMouse. Do not terminate programs without
  calling DoneMyMouse.

  You need not call DoneMyMouse before closing graphics via Gr.CloseGraphics.
  MyMouse waits for messages from CloseGraphics, and will deactivate itself.

  If InitEvents had not been called before the InitMyMouse call, DoneMyMouse
  will call DoneEvents.

function MouseInstalled: Boolean;

  This function returns true if a mouse is connected and MyMouse can be
  initialized.

procedure ReserveMouseSeg;

  This procedure allocates the memory used for cursor background storage.
  Do NOT call this procedure. Any memory management is done automatically.

procedure SetBGIMode(Driver, Mode: Integer);

  By this procedure, you can set the Gr Mode indirectly, specifying the
  parameters of Graph.InitGraph.
  This method has become obsolete and should not be used.

procedure GetMouseEvent(var Event: TEvent);

  This procedure calls Drivers.GetMouseEvent in order to get a mouse
  event.

procedure GetTimerEvent(var Event: TEvent);

  This procedure generates an event of the class evTimer if at least 1/18.2
  sec have passed since last call (i.e. a timer interrupt has happened).
  The InfoWord member is loaded with the timer count.

procedure SetMousePos(x, y: Integer);

  This procedure moves the mouse cursor to the specified position. You
  need not hide the mouse before.

procedure SetMouseArea(x1, y1, x2, y2: Integer);

  This procedure sets the screen region in which the mouse may appear. If
  the mouse is outside the specified rectangle, it will be moved inside.
  NOTE: Turbo Vision notation is used, i.e. the x2, y2 co-ordinates are
	just outside the specified region.

procedure SetMousePage(Page: Byte);

  This procedure sets the screen page in which the mouse is to be drawn.
  You need not hide the mouse before.

procedure SetCriticalArea(x1, y1, x2, y2: Integer);

  This procedure sets the rectangular region in which HideMouse and ShowMouse
  shall take effect. This region should (especially in graphic user
  interfaces) be only the real drawing area, so that flickering of the
  cursor can be prevented. The cursor is redrawn or hidden by this procedure
  if necessary.
  NOTE: Turbo Vision Notation is used, i.e. the coordinates x2, y2 are
	just outside the region.

procedure SetCriticalPage(Page: Byte);

  This procedure sets the screen page on which HideMouse and ShowMouse
  shall take effect. The cursor is redrawn or hidden by this procedure
  if necessary.

procedure SetMCursor(n: Integer);

  This procedure chooses the mouse cursor by its identification number. You
  need not hide the mouse cursor before.
  NOTE: Use the mcXXXX constants for n.

  You may use SetMCursor within ChangeCursor service routines. Thus, no
  direct access to the NewNum variable is required. For compatibility with
  later versions, never access NewNum directly.

procedure SetPointerColor(AColor: Byte);

  This procedure sets the cursor color to be used. You need not hide the
  mouse cursor before.

  You may use SetPointerColor within ChangeCursor service routines. Thus, no
  direct access to the PointerColor variable is required. For compatibility
  with later versions, never access PointerColor directly.

procedure SetCursorPtr(p: pointer);

  This procedure sets the mouse cursor by a pointer to its defining structure.

  You may use SetPointerColor within GetMCursor service routines. Thus, no
  direct access to the CursorPtr variable is required. For compatibility
  with later versions, never access CursorPtr directly.

procedure ShowMouse;

  This procedure increases the internal MouseHidden count. If it reaches 0,
  the mouse cursor is drawn.

procedure HideMouse;

  This procedure decreases the internal MouseHidden count and hides the
  mouse if necessary.

procedure SetDoubleSpeedTreshold(Value: Word);

  This procedure sets the DoubleSpeedTreshold value. This is the relative
  speed of the mouse to be reached for doubling cursor's speed.


Following routines are semi-internal ones. They are in the interface, so that
external service routines may use them.

procedure MSaveRegs;

  Stores the VGA registers that are changed by the service routines.

procedure RestoreRegs;

  Restores these VGA registers.


This is a nice utility routine provided by MyMouse for historical reasons.

procedure MakeContain(var P: TPoint; R: TRect);

  Changes the co-ordinates of the given point, so that it it will take place
  inside the specified rectangle.


3. Variables
------------

Identifier	Type	Description				Notes
---------------	-------	---------------------------------------	-----------
MouseMode	Word	Current mouse operation mode		R/O
ButtonCount	Byte	Number of mouse buttons			R/O   DRI
MouseSaveSeg	Word	Real mode segment for cursor background	R/O
MouseSavePtr	pointer	Address of memory for cursor background	R/O
MouseSavePOfs	Word	(offset)				R/O
MouseSavePSeg	Word	(segment)				R/O
MouseWhere	TPoint	Mouse co-ordinates			R/O   DRI
MouseButtons	Byte	Mouse button state			      DRI
MouseArea	TRect	Mouse working area			R/O
MousePage	Byte	Mouse working screen page		R/O
MousePagePtr	pointer	Adrress of mouse screen page		R/O
MousePageLinear	LongInt	Linear screen address of mouse page	R/O
CriticalArea	TRect	Critical screen region			R/O
CrticalPage	Byte	Critical screen page			R/O
CursorNum	Word	Current cursor				1
CursorPtr	pointer	Pointer to current cursor bitmap	1
NewNum		Word	New cursor				2
PointerColor	Byte	Current cursor color			R/O
MouseHidden	Integer	Internal Hide/ShowMouse counter		R/O
MaxWidth	Byte	Maximal cursor width in data bytes	3
MaxLength	Byte	Maximal cursor height in pixels		3
DoubleDelay	Word    (see reaction delays)			      DRI
RepeatDelay	Word	(see reaction delays)			      DRI
AutoDelay	Word	(see reaction delays)			      DRI
DoubleSpeed-	Word	Relative mouse speed for doubling	R/O
   Treshold		cursor speed
AutoSpeed	Word	w/o function - for compatibility only
ChangeCursor	proc	Cursor adaption
GetMCursor      TGetMC#	Get cursor bitmap
DrawMouse	proc	Cursor drawing
SaveScreen	proc	Background storing
RestoreScreen	proc	Background restoring
SaveLatches	proc	Latches storing
RestoreLatches	proc	Latches restoring
Port1		Word	Port address of COM1			      40H
Port2		Word	Port address of COM2			      40H

Abbreviations

R/O	READ-ONLY: This variable may not be modified directly.
	Use the respective routines for setting the values.
DRI     This variable is declared absolute to a variable in Drivers unit.
40H	This variable is declared absolute to a memory value in the BIOS
	segment 40H.
1	This variable may only be set in a GetMCursor service routine.
	For compatibility with later versions, do not set it directly.
2	This variable may only be set in a ChangeCursor service routine.
	For compatibility with later versions, do not set it directly.
3	These variables are to be set before the InitMyMouse call.

Reaction delays

Read about these values in the Drivers documentation. In contrast to previous
versions of MyMouse, Drivers generates all mouse events, so that the
reaction delays of Drivers are to be set.

AutoDelay is another identifier for RepeatDelay; it is included to keep
compatibility. The AutoSpeed variable controlled the distance between
evMouseAuto events in previous versions. This is not supported any more.


4  Mouse Cursor Design
----------------------

The global procedural GetMCursor variable points to a far procedure that
assigns the CursorPtr variable a pointer to the mouse cursor glyph. The
cursor identifier is handed over as a parameter. Following is the structure
of a mouse cursor:

  - 2 bytes length of the cursor in pixels
  - 2 bytes width of the cursor in 8 pixels
  - 2 bytes for hotspot x and y each
  - ScreenMask (as many bytes as needed)
  - PixelMask (as many bytes as needed)

Normally, GetMCursor points to a procedure in the MyMouse unit. GetMCursor
is declared as procedure(n: Integer) and must be far. In your own GetMCursor
procedure, you must do the following:

 (a)  Test, whether the required cursor is provided by your routine.
 (b)  If yes, set CursorPtr and CursorNum (set to value of param)
      appropriately.
 (c)  Else, call the old GetMCursor routine.

Do not forget to define your own mcXXXX constants, so that you can
comfortably access the cursor types.


Mouse Cursor Glyphs
-------------------

In MyMouse, cursor may be come as wide and high as you want. The larger
the cursors get, the more memory is needed for storing the cursor's
background. Therefore, the size of cursors is normally limited to 16 x 32
pixels.
You may change the MaxWidth and MaxLength variables BEFORE the InitMyMouse
call if you want to have larger cursors. As experience shows, larger cursors
than 64 x 64 pixels are not very sensible. In the 256-color mode, the
maximal width is 16 pixels.

The hotspot characterizes the point inside the mouse cursor that is pointed
by the cursor.

Screen mask and pixel mask make up the cursor glyph.
Bits set in the screen mask make the corresponding pixels black (nAND).
The pixel mask is then xorred with the screen. By combining screen and pixel
mask, you will come to four screen manipulations:

  SM  PM    Manipulation
  0   0     none
  0   1     inverts pixel
  1   0     turns pixel into black
  1   1     turns pixel into white

The bits are mapped to the screen pixels as a word is written in binary
(higher bits are mapped to the left).

Please have a look at the sources of the examples for better understanding.


5  Automatic Cursor Adaption to GUI Elements
--------------------------------------------

In graphical user interfaces (GUI), it is useful to adapt the cursor to the
GUI element it points to. In input lines, for example, the cursor may become
a vertical beam; at window frames it may become a double arrow.
This adaption is no problem with the MyMouse unit. You just have to write
a control routine, which returns the needed cursor in dependence upon
the current mouse position since MyMouse does not know your GUI's conception.

The procedural ChangeCursor variable normally points to a dummy procedure.
If you want to change the cursor behavior, implement a (global and far-coded)
procedure that sets the NewNum variable (new cursor type number) in dependence
upon the current coordinates in MouseWhere.


6  User Service Routines
------------------------

Five procedural variables contain the procedures that do the real work:

  DrawMouse		cursor drawing routine
  SaveScreen		background saving routine
  RestoreScreen		background restoring routine
  SaveLatches		VGA latches saving routine
  RestoreLatches	VGA latches restoring routine

Only change these values if you know what you are doing!

-----------------------------------------------------------------------------
				New in Version 1.6
-----------------------------------------------------------------------------

1  SuperVGA VESA support for high-resolution 256-color modes.
2  Anti-flickering logic.
3  Intelligent reaction on graphics mode switches.
4  Hardware-event double-buffering.

-----------------------------------------------------------------------------
				New in Version 1.5
-----------------------------------------------------------------------------

1  MyMouse now co-operates with all mice in its driver mode.
2  MyMouse now directly supports Mouse Systems mice.
3  Mouse cursors can now become also as wide as you want.
4  MyMouse's code has become more compact and faster.
5  MyMouse's events now match to Drivers' events.
6  MyMouse now co-operates with MS Windows even when the application is
   executed in the 386 enhanced mode in a window.
7  MyMouse now supports the ports and the IRQs still more flexible.
8  MyMouse now supports besides the mouse page also a critical page.
9  New routines make the usage easier:
   SetMousePos, SetPointerColor, SetDoubleSpeedTreshold etc.

