UNIT Mouse;

{***************************************************************************}
{																			}
{		Author:				Kevin A. Lee									}
{																			}
{		Last Amended:		22nd January, 1993								}
{																			}
{		Description:		Turbo Pascal V6 Mouse routines.          		}
{																			}
{							These routines are intended for use with the	}
{							pasKAL graphics library. Therefore they will	}
{							only work with a screen resolution of 320x200	}
{							pixels. For other resolutions you should 		}
{							purchase the source code which gives help		}
{							on how to achieve this.							}
{																			}
{***************************************************************************}


INTERFACE

uses
	MCGA256, DOS, Crt;

const
	LeftButton   = 1;			{ 0000 0010 Left button pressed }
    RightButton  = 2;           { 0000 1000 Right button pressed }
    MiddleButton = 4;			{ 0010 0000 Middle button pressed }

type
	MouseEvent = record	             	{ mouse event type }
    	xpos, ypos: word;				{ the current mouse position }
        button: word;					{ the number of the button pressed }
    end;

	MouseCursorShape = record			{ mouse cursor shape type }
    	mask: array[1..32] of word; 	{ shape of mouse cursor }
        xHot, yHot: word;				{ hotspots of cursor }
    end;


function InitialiseMouse(var buttons: word): boolean;
{																		   	}
{	Parameters:			buttons - the number of buttons available.			}
{																			}
{	Returns:			true if mouse is available else false.				}
{																			}
{	Description:		Initialises the mouse if one is available, else		}
{						returns accordingly.								}


procedure ShowMouse;
{																			}
{	Description:		Puts the mouse cursor on the screen.				}
{						NOTE: the calls ShowMouse and HideMouse are			}
{						cumulative.											}


procedure HideMouse;
{																			}
{	Description:		Hides the mouse cursor.								}
{						This routine should be used whenever you write		}
{						directly to the screen.								}


procedure MouseShape(var shape: MouseCursorShape);
{																			}
{	Parameters:			shape - the mouse cursor including hotspots.		}
{																			}
{	Description:		Sets the mouse cursor shape and hotspots according	}
{						to the variable 'shape'.							}


procedure GetMousePosition(var x, y, button: word);
{																			}
{	Parameters:			x, y - the coordinates of the mouse cursor.			}
{						button - the button status:               			}
{							-	Bit 0 = left, 1 = right, 2 = centre;		}
{																			}
{	Description:		Gets the current mouse position and button status.	}


procedure SetMousePosition(x, y: word);
{																			}
{	Parameters:			x, y - new coordinates of mouse cursor.				}
{																			}
{	Description:		Sets the mouse position to the coordinates 			}
{						specified.											}

procedure LastMousePress(var x, y, which, button, count: word);
{																			}
{	Parameters:			x, y - cursor position at last button press.		}
{						which - button of interest.	(0 = L, 1 = R, 2 = C)	}
{						button - button status.								}
{						count - number of presses.							}
{																			}
{	Description:		Gets the button press information of the button		}
{						passed via the variable 'which'.					}


procedure LastMouseRelease(var x, y, which, button, count: word);
{																			}
{	Parameters:			x, y - cursor position at last button releaase.		}
{						which - button of interest.	(0 = L, 1 = R, 2 = C)	}
{						button - button status.								}
{						count - number of release.							}
{																			}
{	Description:		Gets the button release information of the button	}
{						passed via the variable 'which'.					}

procedure MouseLimits(xMin, yMin, xMax, yMax: word);
{																			}
{	Parameters:			xMin, yMin, xMax, yMax - new rectangle in which		}
{						mouse cursor is to be restricted.					}
{																			}
{	Description:		Limits the cursor to the area specified.			}


function GetMouseEvent(var ev: MouseEvent): boolean;
{																			}
{	Parameters:			ev - the event which occurs.						}
{																			}
{	Returns:			true if a mouse event has occured else false.		}
{																			}
{	Description:		Gets the current mouse position and button status	}
{						and returns them in the MouseEvent record passed.	}
{						If the record has changed since the last time the	}
{						the routine was called true is returned else false	}
{						is returned.										}



IMPLEMENTATION


type
	MouseInfo = record
        xLast, yLast: word;
        buttonLast: word;
    end;

var
	Mi: MouseInfo;		{ internal information used by mouse functions }
	xFactor: word;		{ factor to divide x coordinates by }


{ procedure to call mouse interrupt with relevant registers sent/returned }
procedure CallMouse(service: word; var ax, bx, cx, dx, es: word);
var
	r: registers;
begin
	r.ax := service;
    r.bx := bx;
    r.cx := cx;
    r.dx := dx;
    r.es := es;
    intr($33, r);
    ax := r.ax;
    bx := r.bx;
    cx := r.cx;
    dx := r.dx;
    es := r.es;
end; {CallMouse}



function InitialiseMouse(var buttons: word): boolean;
var
	ax, a: word;
begin
	CallMouse(0, ax, buttons, a, a, a);
    InitialiseMouse := ax = $FFFF;
    xFactor := 640 div MaxX;
end; {InitialiseMouse}



procedure ShowMouse;
var
	a: word;
begin
	CallMouse(1, a, a, a, a, a);
end; {ShowMouse}



procedure HideMouse;
var
	a: word;
begin
	CallMouse(2, a, a, a, a, a);
end; {HideMouse}



procedure MouseShape(var shape: MouseCursorShape);
var
	dx, es: word;
begin
   	es := seg(shape.mask);
    dx := ofs(shape.mask);
    CallMouse(9, dx, shape.xHot, shape.yHot, dx, es);
end; {MouseShape}



procedure GetMousePosition(var x, y, button: word);
var
	a: word;
begin
	CallMouse(3, a, button, x, y, a);
    x := x div xFactor;
end; {GetMousePosition}



procedure SetMousePosition(x, y: word);
var
	a: word;
begin
	x := x * xFactor;
    CallMouse(4, a, a, x, y, a);
end; {SetMousePosition}



procedure LastMousePress(var x, y, which, button, count: word);
var
	a: word;
begin
	CallMouse(5, button, which, x, y, a);
    x := x div xFactor;
    count := which;
end; {LastMousePress}



procedure LastMouseRelease(var x, y, which, button, count: word);
var
	a: word;
begin
	CallMouse(6, button, which, x, y, a);
    x := x div xFactor;
    count := which;
end; {LastMouseRelease}



procedure MouseLimits(xMin, yMin, xMax, yMax: word);
var
	a: word;
begin
	xMin := xMin * xFactor;
    xMax := xMax * xFactor;
    CallMouse(7, a, a, xMin, xMax, a);
    CallMouse(8, a, a, yMin, yMax, a);
end; {MouseLimits}



function GetMouseEvent(var ev: MouseEvent): boolean;
var
	x, y, button: word;
begin
	GetMousePosition(x, y, button);
    GetMouseEvent := false;

    { has something changed? }
    if (Mi.buttonLast <> button) then
    begin
    	Mi.buttonLast := button;
        ev.button := button;
        GetMouseEvent := true;
    end;

    if (Mi.xLast <> x) then
    begin
    	Mi.xLast := x;
        ev.xpos := x;
        GetMouseEvent := true;
    end;

    if (Mi.yLast <> y) then
    begin
    	Mi.yLast := y;
        ev.ypos := y;
        GetMouseEvent := true;
    end;

end; {GetMouseEvent}



begin
	Mi.xLast := 0;
    Mi.yLast := 0;
    Mi.buttonLast := 0;
end.
