*****************************************************************************
*                                                                           *
*                        Graphics Unit For The Mouse                        *
*                                     by                                    *
*                             Jean-Laurent PRADEL                           *
*                                                                           *
*                                 Version 2.0                               *
*                                                                           *
*****************************************************************************



                                 Introduction
                                 ____________


     When I test the TP6 for the first time, my biggest disappointment was
that it was always impossible to program the mouse in graphic mode ! After few
weeks, I found a small book about this under TP5. Just the time for my blood
to make a turn in my body and I make my first try... At this time, I had only
an old 8088 ! (Yeah, really !!!).

     Here you will find the result of my thinking and some system handing up !

     If you don't want to read immediatly all those details, you can try my
demo program which could be programmed in a better way, but it is just here
to show you what I did...


                        o

                              Types and Constants


     In first, there is a type which is used to create the mouse pattern :

         Type MousePattern = Record
                                InsertX : word;
                                InsertY : word;
                                Pattern : Array [0..15] of String [16];
                             End;

     The mouse cursor is a small pattern of 16*16 pixels. The variables
InsertX and InsertY define the INSERTION POINT in this pattern; it is the
point in the pattern which define the mouse position.
     The array contains the shape of the cursor. For exemple, the arrow is
defined by :

      Const Arrow : MousePattern = (InsertX: 2;
                                    InsertY: 1;
                                    Pattern: ('  0             ',
                                              ' 020            ',
                                              ' 0220           ',
                                              ' 02220          ',
                                              ' 022220         ',
                                              ' 0222220        ',
                                              ' 02222220       ',
                                              ' 022222220      ',
                                              ' 0222222220     ',
                                              ' 02222222220    ',
                                              ' 0222222000     ',
                                              ' 02000220       ',
                                              '  0  0220       ',
                                              '      0220      ',
                                              '      0220      ',
                                              '       00       '));

     With my method, there is in the same array the mask and the shape. For
that you need 4 caracters :

     - ' ' (Space Caracter) : The background will be displayed.
     - '0'                  : A black point will be displayed (BkColor).
     - '1'                  : A white point will be displayed (really white).
     - '2'                  : The background will be displayed in the
                              complementary colour.

     I know that it isn't so easy to see the difference between a 1 and a 2
in the middle of others 0, 1 and 2. But it is really easy to type on the
keyboard and easier to read than a set of hexadecimal codes !...

                                  o

     I thought that it was really boring to create a complete box manager when
you get my unit. So I defined an objet :

      Box = Object
              MidX, MidY : Integer;
              Width, Height : Integer;
              COutLine, CInSide, CText : Integer;
              TypText : TextSettingsType;
              Text : String;
              Constructor Init (x,y,w,h : Integer; co,ci,ct : Integer);
              Procedure SetText (Ft, Dir, CSize : Integer; txt : String);
              Procedure Bill; Virtual;
              Procedure UnBill; Virtual;
              Procedure Wait (b : Integer);
              Procedure ChangeColor (co,ci,ct : Integer);
              Procedure Move (nx,ny : Integer);
              Procedure ChangeText (Ft, Dir, CSize : Integer; txt : String);
              Function TestButton (Button : Integer) : Boolean;
              Destructor Done; Virtual;
            End;

     You can define children of this type and change the procedures Bill,
UnBill and Done (they are Virtual).
     The variables are used as follow :
          MidX and MidY : The coordinates of the middle of the box.
          Width : The width of the box (hehe!!).
          Height : The height of the box (hohoho!!).
          COutSide, CInSide and CText : The colors of the border, the inside
                    and the text of the box.
          TypText : The text parameters (direction, font, ...).
          Text : The ... text in the box (Yaouhhh!!!).

     You can use this type as pointer if you don't forget the lows of the
CONSTRUCTOR and the DESTRUCTOR (for this, call your knowledge...).

                                  o

     After that, I have defined 7 constants for the codes of the buttons and
4 others for predefined cursors:


   Left, Middle, Right, LeftMiddle, MiddleRight, LeftRight, LeftMiddleRight

                 Arrow, Target, Bomb and QuestionMark.


     KingOfMouse is a variable which is initialized by the function TestMouse.

                        o

                                   Procedures



Procedure MouseState(Var dx,dy,button:integer);

      This procedure brings you back the position of the mouse and the state
of the button (see constants). dx and dy are the real coordinates between 0
and 639. In CGA mode, the dx coordinate is gave in the range 0..639 (like in
EGA or VGA mode).

                                  o

Procedure ChangeMouse(Drawing:MousePattern);

      This procedure changes the mouse cursor with the variable Drawing. The
type MousePattern was explained just before.

                                  o

Procedure Show_Mouse;

      This procedure shows the mouse!!! You must be care, the same procedure
exists in the Drivers unit of TurboVision, but it is called "ShowMouse" and
not "Show_Mouse"!!!

                                  o

Procedure Hide_Mouse;

      This procedure hides the mouse (yeah, really!)!!! And...? You must be
care because blablabla... blabla... blablabla... "HideMouse" blablabla...
"Hide_Mouse"!!!
      Nevertheless, it is important to hide the mouse before drawing anything
in the background, if you don't want to see some strange things on the screen.

                                  o

Procedure PutMouse(x,y:integer);

      This procedure moves the mouse to the point (x,y). You don't need to use
Hide_Mouse before this procedure (and of course to use Show_Mouse after).

                                  o

Procedure WaitButton (Var a,b,button:integer);

      This procedure waits (!) the user clicks a button and gives you back
the coordinates of the mouse at this moment and which button was used.

                                  o

Procedure MouseLimits (x1,y1,x2,y2:integer);

      This procedure defines a box (x1,y1),(x2,y2) out of which the mouse
can't go. The upper left corner has (0,0) as coordinates...

                                  o

Procedure UnLimitMouse;

      This procedure deletes the limits made by the procedure MouseLimits.

                                  o

Procedure LastPress (Var x,y,number,button:integer);

   This procedure gives you back some informations about the button "button" :
         x : last position x of the mouse when "button" was pressed.
         y :   -     -     y -   -    -    -       -     -     -   .
         number : How many times the "button" has been pressed since the last
                  call to this procedure.
         button : How are the buttons now... (see constants).


                                  o

Procedure LastRelease (Var x,y,button:integer);

   This procedure gives you back some informations about the button "button".
This procedure works like the procedure LastPress.

                                  o

Procedure MouseRun (Var a,b:integer);

      This procedure gives you the moving of the mouse since the last call.
Those values are in 1/200 inches (generally called 'mickey'). They are
positives from left to right and from top to bottom. 

                                  o

Procedure MouseSpeed (a,b:integer);

      This procedure is used to fixe the rate between mickeys and pixels.
Those news values must be given in mickeys per 8 pixels (max. 32767).
The horizontal default value is 8 and the vertical default value is 16.

                                  o

Procedure Box (x,y,l,h,ctour,cint,ctext:word;text:String);

      This procedure has nothing to do with the mouse, but I think that it is
really usefull. It draws a box, centred on (x,y), with a length of l and a
height of h. The color of the border is ctour, that of the inside is cint. You
can put a text in with the colour ctext.

                        o

                                   Functions


Function TestMouse:Boolean;

      This function is the first thing that you MUST do in your initialization
procedure. This function tests the driver of the mouse.
      If there is no driver, the result is False.
      If there is a driver active, the result is True.
      More, this function initializes the variable KindOfMouse which gives you
the number of buttons on the mouse.

                                  o

Function TestButton(x1,y1,x2,y2,button:integer):boolean;

      This function becames True if the mouse is in the box (x1,y1),(x2,y2)
and the button "button" is pressed. In any other case, the function is False.

                        o

                                   Object BOX

Constructor Box.Init (x,y,w,h : Integer; co,ci,ct : Integer);

     This procedure is the CONSTRUCTOR of the object, you MUST use it to
initialize an object. This just initialize the variables MidX, MidY, Width,
Height, COutSide, CInSide and CText. But it also creates the VMT...

                                  o

Procedure Box.SetText (Ft, Dir, CSize : Integer; txt : String);

     This procedure initialize the text of the box : font, direction, size
and text. If the text it's too long to fit in the box, then the width and the
height are adjusted.

                                  o

Procedure Box.Bill; Virtual;

     This procedure draws the box (...!!). It hides the mouse, draws the box
with its colors, restores the currents colors (used by the rest of the
program) and shows the mouse.

                                  o

Procedure Box.UnBill; Virtual;

     This procedure undraws the box (huhu!!). Like Box.Bill, this procedure
hides the mouse, restores the currents colors and shows the mouse.

                                  o

Procedure Box.Wait (b : Integer);

     Waits that the user clicks in the box with the button 'b' (see constants)

                                  o

Procedure Box.ChangeColor (co,ci,ct : Integer);

     Changes the values of the variables COutSide, CInSide and CText with the
news values co, ci, ct and draws the "new" box.

                                  o

Procedure Box.Move (nx,ny : Integer);

     Changes the values MidX and MidY only if the entire box it's always in
the screen.

                                  o

Procedure Box.ChangeText (Ft, Dir, CSize : Integer; txt : String);

     Changes the text, tests that the box is big enough (adjust if useful)
and draws the "new" box.

                                  o

Function Box.TestButton (Button : Integer) : Boolean;

     Returns 'True' if the 'Button' is pressed in the box. This function
doesn't wait, but just make a test "in the run". Very useful to finish the
loops Repeat .......... Until "the user click in box". (Really !!!)

                                  o

Destructor Box.Done;

     The DESTRUCTOR ! It just deletes the box and cleans the VMT. It's
essential to use it if you make pointers with the type Box.

                        o

                                That 's all !!!


      That 's all, but not at all!!! This unit is the first thing which lives
Bob (Bob is my computer) and my house (euh... my appartment). And of course,
it is possible to do better (with my program and with my english !).
      So, I will be very happy if you send me some echos of what happens with
my unit.
      I already know a "problem"... : When you run Windows, this program
changes something in your driver. After that, your driver only recognizes 2
buttons (even if you have a lovely mouse with 3 buttons), and my unit only
sees a mouse with 2 buttons !!!.

      The bigger problem that I know is that my unit doesn't work in SVGA
mode. I'm really disappointed by this !!! I don't know the solution (for the
moment). If you (yes, YOU) have an idee or if you already program directly
a graphic card (by using the interruption 10h), you could help me...!


      Until May 93:                      After May 93:

      Jean-Laurent PRADEL                Jean-Laurent PRADEL
      Im Sohlgraben 1A                   Ch. Piegros Sud
      D-3550 MARBURG/CAPPEL              Villa Le Sapin Bleu
      Germany                            83170 BRIGNOLES
                                         France

      E-Mail : pidou@astro.chemie.uni-marburg.de

      Thank you and a lot of fun....................Danke und viele Spa
