Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TurboPascal Mouse Driver Source code needed

1 view
Skip to first unread message

Bob Schmitt

unread,
Nov 29, 1995, 3:00:00 AM11/29/95
to
I'm looking for source code for mouse routines. I've got a word
processor app that I would like to add mouse support to. It's a
DOS base text mode app. It would be nice
if the mouse routines would include
autodetect and also handle updating the screen mouse pointer based on mouse
movements. Then I would just have to handle mouse buttons depressions
and releases. This is an elderly app which I would like to give a little more life to.
I compile it under TurboPascal V6.0 and don't have the new compiler. I would
like to get by without getting the latest compiler and going through the process
of getting my program to work again. So I would hope that the mouse code
would also compile under 6.0.

>>> Bob <<<

Todd Lang u

unread,
Nov 29, 1995, 3:00:00 AM11/29/95
to
Here is some code that I wrote, with a piece of code from some library
somewhere or another thrown in to accomplish a function I never actually
needed. *8) Isn't that always the way?

It's kinda sloppy, and, of course, not documented...but I think the
function names speak for themselves. You can e-mail me if you need help
with it or whatever.


If you cut here, you ruined your monitor!
=========8<---------------------------------------------------------------
unit cgmouse;

interface

uses crt,dos;
var
regs : registers;
type
onoff = (on,off);

function initmouse : boolean;
procedure mousecursor(com : onoff);
function getmousex : integer;
function getmousey : integer;
procedure setmouse(x,y : integer);
function button : integer;
procedure mwindow(x1,y1,x2,y2:integer);
PROCEDURE set_pointer( hotx, hoty : Word;image : POINTER );
FUNCTION get_bufsize: Word;
PROCEDURE get_state(state : POINTER );
PROCEDURE set_state(state : POINTER );
PROCEDURE HideRegion( top, left, bottom, right : Word );

implementation

FUNCTION PSeg( x : POINTER ) : Word; INLINE( $5a/$58 );
FUNCTION POfs( x : POINTER ) : Word; INLINE( $58/$5a );


function initmouse: boolean;
begin
regs.ax:=$00;
intr($33,regs);
if regs.ax=0 then
initmouse := false;
if regs.ax=-1 then
initmouse := true;
end;

procedure mousecursor(com : onoff);
begin
if com = off then
begin
regs.ax := $02;
intr($33,regs);
end;
if com = on then
begin
regs.ax := $01;
intr($33,regs);
end;
end;

function getmousex : integer;
begin
regs.ax := $03;
intr($33,regs);
getmousex := regs.cx;
end;

function getmousey : integer;
begin
regs.ax := $03;
intr($33,regs);
getmousey := regs.dx;
end;

procedure setmouse(x,y : integer);
begin
regs.ax := $04;
regs.dx := y;
regs.cx := x;
intr($33,regs);
end;

function button : integer;
begin
regs.ax := $03;
intr($33,regs);
button := regs.bx;
end;

procedure mwindow(x1,y1,x2,y2 : integer);
begin
regs.ax := $08;
regs.cx := y1;
regs.dx := y2;
intr($33,regs);

regs.ax := $07;
regs.cx := x1;
regs.dx := x2;
intr($33,regs);
end;

{==============================================================
ms_set_graphPointer real-mode mouse function 9
==============================================================
hotx, hoty (+/-16) are the hot spot coordinates relative to
the upper-left of the pointer image.
image = pointer to the mouse pointer image bitmap
The first 32 bytes define the screen mask
The last 32 bytes define the pointer mask
The pointer is drawn by:
AND screen mask with pixels under the pointer,
XOR pointer mask with result
In mode 6, each bit defines the color of a pixel.
In modes 4 and 5, each pair of bits defines the color of a
pixel.
}
PROCEDURE set_pointer( hotx, hoty : Word;
image : POINTER );
BEGIN
regs.AX := 9;
regs.BX := hotx;
regs.CX := hoty;
regs.DX := POfs(image);
regs.ES := PSeg(image);
Intr($33,regs);
END;
{================================================================
ms_get_state_bfsz real-mode mouse function 21
================================================================
Return buffer size in bytes required to save the mouse driver
state.
}
FUNCTION get_bufsize: Word;
BEGIN
regs.AX := 21;
Intr($33,regs);
get_bufsize := regs.BX;
END;


{================================================================
ms_get_state real-mode mouse function 22
================================================================
Get the mouse driver state.
}
PROCEDURE get_state(state : POINTER );
BEGIN
regs.AX := 22;
regs.DX := POfs(state);
regs.ES := PSeg(state);
Intr($33,regs);
END;


{================================================================
ms_set_state real-mode mouse function 23
================================================================
Set mouse driver state, given a previously saved state.
}
PROCEDURE set_state(state : POINTER );
BEGIN
regs.AX := 23;
regs.DX := POfs(state);
regs.ES := PSeg(state);
Intr($33,regs);
END;


PROCEDURE HideRegion( top, left, bottom, right : Word );
VAR Regs : Registers;
BEGIN
Regs.AX := 16;
Regs.CX := left;
Regs.DX := top;
Regs.SI := right;
Regs.DI := bottom;
Intr($33,Regs);
END;

end.

Bob Schmitt

unread,
Dec 6, 1995, 3:00:00 AM12/6/95
to
In article <DItC8...@info.uucp>, lang...@mach1.wlu.ca (Todd Lang u) says:
>
>Here is some code that I wrote, with a piece of code from some library
>somewhere or another thrown in to accomplish a function I never actually
>needed. *8) Isn't that always the way?
>
>It's kinda sloppy, and, of course, not documented...but I think the
>function names speak for themselves. You can e-mail me if you need help
>with it or whatever.
> [deleted].

>function button : integer;
>begin
> regs.ax := $03;
> intr($33,regs);
> button := regs.bx;
>end;

Thanks, for providing the source code.
I put a function similar to your button function in my main loop. My problem is
that my main loop does a lot of other processing (updating the screen,
printing, etc) and sometimes mouse button presses are missed. Is there
any way to check and see if a button has been pressed between the last time
the mouse was checked and this time?

>>> Bob <<<

Fulko van Westrenen

unread,
Dec 8, 1995, 3:00:00 AM12/8/95
to
Did you check the SWAG libraries? I found SWAG to be very useful for the mouse.

Fulko

Eddy

unread,
Dec 8, 1995, 3:00:00 AM12/8/95
to
Bob Schmitt (rs0...@medtronic.com) wrote:
> [...]

> I put a function similar to your button function in my main loop. My problem is
> that my main loop does a lot of other processing (updating the screen,
> printing, etc) and sometimes mouse button presses are missed. Is there
> any way to check and see if a button has been pressed between the last time
> the mouse was checked and this time?


I didn't follow this thread, but if I'm not misunderstood it, use this:

use function 5h to get the last button pressed, and function 6h to get the
last button released.
BX = button you interested in.
CX and DX = the location of the mouse cursor(in mickey)

Good luck...

--
-Eddy

Jon Emmett

unread,
Dec 9, 1995, 3:00:00 AM12/9/95
to rs0...@medtronic.com
rs0...@medtronic.com (Bob Schmitt) wrote:
>In article <DItC8...@info.uucp>, lang...@mach1.wlu.ca (Todd Lang u) says:
>>
>>Here is some code that I wrote, with a piece of code from some library
>>somewhere or another thrown in to accomplish a function I never actually
>>needed. *8) Isn't that always the way?
>>
>>It's kinda sloppy, and, of course, not documented...but I think the
>>function names speak for themselves. You can e-mail me if you need help
>>with it or whatever.
>> [deleted].

>>function button : integer;
>>begin
>> regs.ax := $03;
>> intr($33,regs);
>> button := regs.bx;
>>end;
>
>Thanks, for providing the source code.
>I put a function similar to your button function in my main loop. My problem is
>that my main loop does a lot of other processing (updating the screen,
>printing, etc) and sometimes mouse button presses are missed. Is there
>any way to check and see if a button has been pressed between the last time
>the mouse was checked and this time?
>
>>>> Bob <<<

Yes there is, setting regs.ax to $05 returns the number of times the
buttons have been pressed, so says a book I have, I haven't had time to
actually try it.You set the regs.bx as either 1 (to test the right button)
or 0 to test the left button. The number of times the button has been
pressed is returned in the bx register, and cx and dx hold the coordinates
of the last place the button was pushed. Try that to see if it actually
works because I really don't know. Sorry :)

Erik Pischel

unread,
Dec 16, 1995, 3:00:00 AM12/16/95
to
On 6 Dec 1995, Bob Schmitt wrote:
[a lot of stuff deleted. It said how to detect when a mouse button is
pressed]

>My problem is
>that my main loop does a lot of other processing (updating the screen,
>printing, etc) and sometimes mouse button presses are missed. Is there
>any way to check and see if a button has been pressed between the last time
>the mouse was checked and this time?
>

My advice is to establish a mouse event queue: There is a mouse handler
function where you can pass a pointer to a procedure that is then called
every time a mouse event happens. You can also pass a mask for those
events, i.e. you can determine what a "mouse event" actually is, e.g. a mouse
click.

Here comes an example for it. I used it for a simple but effective
graphical interface of a demo program. The example exists of 2 Units and
1 assembler file (that means that you have to use TASM!). Please note that
you will find only german comments mostly. But most proc/var names are in
english.
===========================================================================
First the unit "messis" (a german colleq. expression for "messages").
It defines the event-queue. It uses TurboVision alike structures - without
using any TV-Unit or object.
---------------------------------------------------------------------------
UNIT Messis;
{*************************************************
Program : UNIT Messis
File : Messis.pas
Author : Erik Pischel
Date : 11.03.1995

used units: -
required Files: -

description: basis of an event-queue-system

*************************************************}
INTERFACE


const evNothing = 0;
evMouse = 1;
evMessage = 2;
type
TPoint = record
x,y: Word;
end;

TEvent = record
What: Word;
case Word of
evNothing: ();
evMouse: (
Buttons: Byte;
Where: TPoint);
evMessage: (
Command: Word;
case Word of
0: (InfoPtr: Pointer);
1: (InfoLong: Longint);
2: (InfoWord: Word);
3: (InfoInt: Integer);
4: (InfoByte: Byte);
5: (InfoChar: Char));
end;


PEreignis = ^TEreignis;
TEreignis = record
ThisEvent: TEvent;
Next: PEreignis;
end;

procedure GetMessage(Var Event: TEvent);
procedure PutMessage(command: Word;Info: LongInt);

IMPLEMENTATION
var QueueBase: PEreignis;

procedure GetMessage(Var Event:TEvent);
var P: PEreignis;
begin
if QueueBase<>NIL then begin
P:=QueueBase;
if p^.next=NIL then begin
event:=P^.thisevent;
queuebase:=NIL;
end else begin
QueueBase:=P^.next;
Event:=P^.ThisEvent;
end;
Dispose(P);
end else
Event.what:=evNothing;
end;

procedure PutMessage(Command: Word;INfo: LongInt);
{ mousevent an kette anhängen }
var P,q: PEreignis;
begin
new(P);
P^.next:=NIL;
with p^.thisevent do begin
infolong:=info;
what:=evmessage;
end;
p^.thisevent.command:=command;
q:=Queuebase;
if queuebase=NIL then queuebase:=P
else begin
while q^.next<>NIL do q:=q^.next;
q^.next:=p;
end;
end;

var oldexitproc: Pointer;

procedure qexit; far;
var e: TEvent;
begin
exitproc:=Oldexitproc;
repeat
getmessage(e);
until e.what=evnothing;
end;


begin
oldexitproc:=exitproc;
exitproc:=@qexit;
end.
==========================================================================
Second is the unit "mbasics" (which stands for mouse basics). It registers
the mouse clicks and adds them to the event queue. Also have some other
proc like showmouse and hidemouse.
--------------------------------------------------------------------------
UNIT MBasics;
{*************************************************
Program : Unit MBasics
File : MBASICS.PAS
Author : Erik Pischel
Date : 11.03.1994

used units: messis
required files: mousepa.obj

Desciption: implements some (partly special) mouse routines

*************************************************}

INTERFACE
uses messis;

var MouseEnabled :Boolean;

procedure GetMouseEvent(Var Event: TEvent);
procedure PutMouseEvent(Buttons: Integer; x,y: Word);
procedure ResetMouse;
procedure ShowMouse;
procedure HideMouse;
procedure MouISetEventHandler( Event : integer; P :pointer );
procedure DisableMouse;
procedure EnableMouse;
procedure AssHand ;

IMPLEMENTATION
var QueueBase: PEreignis;

{$L mousepa} { das Assembler-Modul einbinden }
{== Deklaration externer Funktionen ===================================}

{$F+} { die Funktion ist FAR }
procedure AssHand ; external ; { der Assembler-Event-Handler }
{$F-} { FAR-Funktionen nicht mehr erzwingen }

procedure GetMouseEvent(Var Event:TEvent);
var P: PEreignis;
begin
if QueueBase<>NIL then begin
P:=QueueBase;
if p^.next=NIL then begin
event:=P^.thisevent;
queuebase:=NIL;
end else begin
QueueBase:=P^.next;
Event:=P^.ThisEvent;
end;
Dispose(P);
end else
Event.what:=evNothing;
end;

procedure PutMouseEvent(Buttons: Integer; x,y: Word);
{ mousevent an kette anhängen }
var P,q: PEreignis;
begin
new(P);
P^.next:=NIL;
p^.thisevent.buttons:=buttons;
with p^.thisevent do begin
where.x:=x;
where.y:=y;
what:=evmouse;
end;
q:=Queuebase;
if queuebase=NIL then queuebase:=P
else begin
while q^.next<>NIL do q:=q^.next;
q^.next:=p;
end;
end;

procedure EnableMouse;
begin
MouseEnabled:=true;
end;

procedure DisableMouse;
begin
MouseEnabled:=false;
end;

procedure ResetMouse; assembler;
asm
mov AX,0;
Int $33;
end;


procedure ShowMouse; assembler;
asm
mov AX,1;
int $33;
end;

procedure HideMouse; assembler;
asm
mov AX,2;
int $33
end;

procedure MouISetEventHandler( Event : integer; P :pointer );assembler;
asm
mov AX,$000C; { Fktnr. für "Set Mouse Handler" }
mov CX,event; { Event-Maske laden }
les dx,p
Int $33 { Maus-Treiber aufrufen }
end;

procedure MouEventHandler( EvFlags, ButState, x, y : integer );
begin
if MouseEnabled then PutMouseEvent(ButState,Word(x),word(y));
end;

var oldexitproc :Pointer;

procedure MouseExit; far;
var e:TEvent;
begin
ExitProc:=OldExitProc;
{1. Maus weg }
HideMouse;
ResetMouse;
{2. Mouse-event-queue weg }
repeat
GetMouseEvent(e);
until (e.what=evNothing);
end;


begin
oldexitproc:=exitProc;
exitProc:=@MouseExit;
mouseenabled:=true;
QueueBase:=NIL;
end.
==========================================================================
Last but not least: mousepa.asm. You need it to compile it to mousepa.obj,
which mbasics uses.
--------------------------------------------------------------------------
;**********************************************************************;
;* M O U S E P A *;
;*--------------------------------------------------------------------*;
;* Aufgabe : Vom Maustreiber aufgerufener Event-Handler *;
;* zur Einbindung in ein Turbo Pascal Programm. *;
;*--------------------------------------------------------------------*;
;* Autor : MICHAEL TISCHER *;
;* entwickelt am : 21.04.1989 *;
;* letztes Update : 11.03.1995 by erik pischel *;
;*--------------------------------------------------------------------*;
;* assemblieren : MASM /MX MOUSEPA; oder *;
;* TASM -MX MOUSEPA; *;
;* ... mit dem Programm MOUSEP verknüpfen *;
;**********************************************************************;

;== Datensegment =======================================================

DATA segment word public
DATA ends ;keine Variablen in diesem Programm

;== Programm ===========================================================

CODE segment byte public ;das Programmsegment
.386

assume CS:CODE ;CS zeigt auf das Codesegment, der In-
;halt von DS, SS und ES ist unbekannt

public AssHand ;gibt dem TP-Programm die Möglichkeit,
;die Adresse des Assembler-Handlers
;zu ermitteln

extrn MouEventHandler : near ;der auzurufende TP-Event-Handler

aktiv db 0 ;zeigt an, ob gerade ein Aufruf aus-
;geführt wird

;-----------------------------------------------------------------------
;-- AssHand : der Event-Handler, der zunächst vom Maustreiber aufgerufen
;-- wird, um seinerseits dann die TP-Prozedur MouEventHandler
;-- aufzurufen
;-- Aufruf von TP: nicht erlaubt!

AssHand proc far
cmp aktiv,0 ;Aufruf noch nicht beendet?
jne ende ;Nein --> Aufruf nicht zulassen
mov aktiv,1 ;keine Aufrufe mehr zulassen
pusha
push es
push ds
;-- die Argumente für den Aufruf der TP-Funktion auf den -----
;-- Stack bringen
;-- Aufruf:
;-- MouEventHandler (EvFlags, ButStatus, x , y : integer );
push ax ;Event-Flags auf den Stack bringen
push bx ;Status der Mausknöpfe auf den Stack
mov di,cx ;horizontale Ordinate in DI merken
mov cl,3 ;Schiebezähler f. Koordinatenumr.
;shr di,cl ;DI (horizontale Ord.) durch 8 teilen
push di ;und auf den Stack bringen
;shr dx,cl ;DX (vertikale Ord.) durch 8 teilen
push dx ;und auf den Stack bringen
mov ax,DATA ;Segmentadresse des Datensegments AX
mov ds,ax ;in von dort in das DS-Register
call MouEventHandler ;Aufruf der TP-Prozedur
pop ds
pop es
popa
mov aktiv,0 ;Aufruf ist wieder erlaubt
ende: ret ;zurück zum Maustreiber

AssHand endp

;-------------------------------------------------------------------------

CODE ends ;Ende des Codesegments
end ;Ende des Programms
--------------------------------------------------------------------------

Now all you have to do is to call the GETEVENT procedure.
You might also add a key-event type, i.e. to put all the pressed keys
in the event list.

Hope this helps.

Take care,
--
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Erik Pischel * email: pis...@informaik.hu-berlin.de +
+ -----------------<PGP key available>---------------------------- +
+ Plesserstrasse 7 * Tel./Fax : +49 30 5368540 +
+ 12435 Berlin * http://www.informatik.hu-berlin.de/~pischel +
+ GERMANY * Heinrich-Hertz-Gymnasium * Berlin F'hain +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

0 new messages