home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
irit
/
drawfuns.arc
/
MOUSEDRV.C
< prev
next >
Wrap
Text File
|
1989-09-06
|
14KB
|
371 lines
/*****************************************************************************
* W A R N I N G : This module assumes mouse driver was installed using *
* one of the following program: mouse.com or mouse.sys. *
* *
* This module can be compiled in any model (tiny..huge) *
* *
* The following routines are available: *
* 1. MouseDetect() - returns TRUE if mouse detected in system. *
* 2. MouseInit() - must be called first before any other call. *
* 3. MouseShowCorsur() - show mouse cursor. *
* 4. MouseHideCorsur() - hide mouse cursor. *
* 5. MouseSetPosition() - set mouse XY position. *
* 6. MouseQueryBuffer() - returns event ring buffer status. *
* 7. MouseQueryDataBuffer() - returns event ring buffer data status. *
* 8. MouseGetBuffer() - returns next event from ring buffer. *
* 9. MouseFlushBuffer() - clear all data currently in buffer. *
* 10.MouseClose() - must be called last before application program dies. *
* *
* Note that as the mouse driver is used asyncronically (i.e. interrupts) *
* fail to call MouseInit() at the begining or even worse, call *
* MouseClose() in the end is an invitation for total system disaster! *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Sep. 1988 *
*****************************************************************************/
/* #define DEBUG /* Uncomment it for simple test routine */
#include <dos.h>
#include <stdio.h>
#include <graphics.h>
#include "GraphGnG.h"
#include "MouseDrv.h"
#include "Program.h"
#ifdef DEBUG
#include <conio.h>
#endif DEBUG
/* Mouse range (start from 0) - MUST be initialized by GraphGen module! */
int MSMouseXmax = 0, MSMouseYmax = 0;
static int MouseVectorInterrupt = 0, /* MouseHandler vector interrupt */
BufferHead, BufferTail, BufferFull, /* Implement ring buffer */
BufferOverRun, /* Over run error in mouse buffer */
MouseBuffer[BUFFER_SIZE][2], /* Mouse event to save. */
WasMouseSetUp = FALSE, /* TRUE - mouse successfully installed */
SkipMouseEvents = 1; /* Number of move events to skip + 1. */
static struct SREGS SRegs;
/**************************************************************************
* Mouse interrupt server. Gets control each time the mouse is moved or *
* one of the buttons was pushed. *
* I realy wanted to try the interrupt function defined in Turbo C, but *
* the mouse calls us with far call... *
* We test 7 interrupts (060h-066h) for unused one (address is NULL) and *
* use that one to interface the interrupt TurboC routine via int 06x. *
**************************************************************************/
static void far MouseInterrupt0(void) { geninterrupt (0x60); }
static void far MouseInterrupt1(void) { geninterrupt (0x61); }
static void far MouseInterrupt2(void) { geninterrupt (0x62); }
static void far MouseInterrupt3(void) { geninterrupt (0x63); }
static void far MouseInterrupt4(void) { geninterrupt (0x64); }
static void far MouseInterrupt5(void) { geninterrupt (0x65); }
static void far MouseInterrupt6(void) { geninterrupt (0x66); }
static void interrupt MouseHandler(void);
static void MouseSysCall(int Func, int *m2, int *m3, int *m4);
/**************************************************************************
* Mouse detect routine. Does three step test: *
* 1. Test if there is none NULL vector in vector interrupt 0x33 which *
* should hold the mouse driver. *
* 2. Test if that pointer is pointing on IRET instruction or not. *
* 3. Test if the mouse is connected by calling to the mouse driver - *
* sys call 0x00. *
**************************************************************************/
int MouseDetect(void)
{
unsigned char far *Ptr;
union REGS Regs;
/* Look if anything is installed in the mouse interrupt vector: */
if (((Ptr = (unsigned char far *) getvect(0x33)) ==
(unsigned char far *) NULL) ||
(*Ptr == 0xcf /* IRET */)) return FALSE;
Regs.x.ax = 0; /* Select reset and test function */
/* interrupt 51 decimal is used by mouse device driver itself: */
int86x(0x33, &Regs, &Regs, &SRegs);
return (Regs.x.ax);
}
/**************************************************************************
* This is the mouse handler itself: called via int 06xh called from the *
* mouse driver through MouseInterruptx()... *
* The x, y coordinates are saved as two integers in the buffer as follows:*
* X is positive if Left Button is pressed, Negative otherwise. *
* Y is positive if Right Button is pressed, Negative otherwise. *
* Note 1 is added to X, Y to make them none zero... *
**************************************************************************/
static void interrupt MouseHandler(void)
{
static int Skip = 0;
int Buttons = _BX, X = _CX, Y = _DX;
if (!Buttons && Skip++ < SkipMouseEvents) return;
Skip = 0;
if (BufferFull) BufferOverRun = TRUE; /* Buffer overflow */
else {
MouseBuffer[BufferHead][0] = (Buttons & 0x01 ? X+1 : -X-1);
MouseBuffer[BufferHead++][1] = (Buttons & 0x02 ? Y+1 : -Y-1);
if (BufferHead == BUFFER_SIZE) BufferHead = 0;
if (BufferHead == BufferTail) BufferFull = TRUE;
}
}
/**************************************************************************
* See all description on all functions available (0-16, 19) on page 54 in *
* Microsoft Mouse manual. *
**************************************************************************/
static void MouseSysCall(int Func, int *m2, int *m3, int *m4)
{
union REGS Regs;
Regs.x.ax = Func; /* Select the requested function */
Regs.x.bx = *m2;
Regs.x.cx = *m3;
Regs.x.dx = *m4;
/* interrupt 51 decimal is used by mouse device driver itself: */
int86x(0x33, &Regs, &Regs, &SRegs);
*m2 = Regs.x.bx;
*m3 = Regs.x.cx;
*m4 = Regs.x.dx;
}
/**************************************************************************
* Mouse Initialization: return NULL if succesful, else error msg string. *
**************************************************************************/
char *MouseInit(void)
{
int i, m2, m3, m4;
void far *MouseIntrAddr;
if (WasMouseSetUp) return (char *) NULL; /* Close old init. first! */
switch (GraphDriver) {
case CGA:
case HERCMONO:
SkipMouseEvents = 2; /* Take every second event! */
break;
case EGA:
case EGA64:
case EGAMONO:
case VGA:
SkipMouseEvents = 4; /* Takes too much time to redraw cursor... */
break;
}
SRegs.ds = _DS; /* In case the communication with the driver needs that */
/* Search for free location in the interrupt vector in 0x60..0x66: */
for (i=0x60; i<0x67; i++) if ((void far *) NULL == getvect(i)) break;
if (i >= 0x67) {
return (char *) "Mouse Install: All interrupts in use (0x60..0x66)\n";
}
MouseVectorInterrupt = i;
BufferHead = BufferTail = 0; /* Reset the Buffer pointers */
BufferFull = BufferOverRun = FALSE;
MouseSysCall(0, &m2, &m3, &m4); /* Install Mouse */
if (MSMouseXmax == 0 || MSMouseYmax == 0) {
GGCloseGraph(); /* Might open other device !? */
fprintf(stderr,
"MouseInit: Mouse range was not initialized by graphic driver\n");
MyExit(1);
}
m3 = 0;
m4 = MSMouseXmax;
MouseSysCall(7, &m2, &m3, &m4); /* Set Column Range */
m3 = 0;
m4 = MSMouseYmax;
MouseSysCall(8, &m2, &m3, &m4); /* Set Row Range */
m3 = (int) (16 / (((double) MSMouseXmax) / 1000));
m4 = (int) (8 / (((double) MSMouseYmax) / 1000));
MouseSysCall(15, &m2, &m3, &m4); /* Set Mickeys Per 8 pixels */
setvect(MouseVectorInterrupt, MouseHandler); /* Link the MouseHandler */
switch (MouseVectorInterrupt) {
case 0x60: MouseIntrAddr = MouseInterrupt0; break;
case 0x61: MouseIntrAddr = MouseInterrupt1; break;
case 0x62: MouseIntrAddr = MouseInterrupt2; break;
case 0x63: MouseIntrAddr = MouseInterrupt3; break;
case 0x64: MouseIntrAddr = MouseInterrupt4; break;
case 0x65: MouseIntrAddr = MouseInterrupt5; break;
case 0x66: MouseIntrAddr = MouseInterrupt6; break;
}
m3 = 0x0b;/* Set bits 0, 1, 3 - interrupt on mouse move & button pressed */
m4 = FP_OFF(MouseIntrAddr);
SRegs.es = FP_SEG(MouseIntrAddr);
MouseSysCall(12, &m2, &m3, &m4); /* Link the MouseInterruptx() routine */
WasMouseSetUp = TRUE;
return (char *) NULL;
}
/**************************************************************************
* Mouse Closing: *
**************************************************************************/
void MouseClose(void)
{
int m2, m3, m4;
if (!WasMouseSetUp) return; /* Install mouse first! */
m3 = 0x00; /* No interrupts any more... */
MouseSysCall(12, &m2, &m3, &m4);
/* Clear that interrupt vector for other uses... */
setvect(MouseVectorInterrupt, (void interrupt (*)()) NULL);
WasMouseSetUp = FALSE;
}
/**************************************************************************
* Routine returns TRUE if buffer is not empty. *
**************************************************************************/
int MouseQueryBuffer(void)
{
return (BufferFull || BufferHead != BufferTail);
}
/**************************************************************************
* Routine to return Mouse buffer status: *
* Returns TRUE if buffer is not empty. In addition sets X, Y, Buttons to *
* the end of buffer without modifying the buffer, and set OverRunError. *
**************************************************************************/
int MouseQueryDataBuffer(int *X, int *Y, int *Buttons, int *OverRunError)
{
if (BufferFull || BufferHead != BufferTail) {
*X = ABS(MouseBuffer[BufferTail][0]) - 1;
*Y = ABS(MouseBuffer[BufferTail][1]) - 1;
*Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
(MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
*OverRunError = BufferOverRun;
return TRUE;
}
else return FALSE;
}
/**************************************************************************
* Routine to get one event from buffer. waits for one if buffer empty. *
* Returns OverRun status - TRUE if over run occurs. In addition sets *
* X, Y, Buttons to the end of buffer, and increment. *
**************************************************************************/
int MouseGetBuffer(int *X, int *Y, int *Buttons)
{
/* Wait for event if buffer is empty: */
while (!(BufferFull || BufferHead != BufferTail));
*X = ABS(MouseBuffer[BufferTail][0]) - 1;
*Y = ABS(MouseBuffer[BufferTail][1]) - 1;
*Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
(MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
disable(); /* No interrupts now! */
if (BufferHead == BufferTail) BufferFull = FALSE;
if (++BufferTail == BUFFER_SIZE) BufferTail = 0;
enable(); /* interrupts o.k. now */
return BufferOverRun;
}
/**************************************************************************
* Routine to flush and clear all the mouse event buffer. *
**************************************************************************/
void MouseFlushBuffer(void)
{
disable(); /* No interrupts now! */
BufferHead = BufferTail;
BufferFull = BufferOverRun = FALSE;
enable(); /* interrupts o.k. now */
}
/**************************************************************************
* Mouse Show Cursor: *
**************************************************************************/
void MouseShowCursor(void)
{
int m2, x, y;
MouseSysCall(1, &m2, &x, &y); /* Show cursor */
}
/**************************************************************************
* Mouse Hide Cursor: *
**************************************************************************/
void MouseHideCursor(void)
{
int m2, x, y;
MouseSysCall(2, &m2, &x, &y); /* Hide cursor */
}
/**************************************************************************
* Mouse Set Position: *
**************************************************************************/
void MouseSetPosition(int X, int Y)
{
int dummy;
MouseSysCall(4, &dummy, &X, &Y); /* Set position */
}
#ifdef DEBUG
/**************************************************************************
* Simple test routine: *
**************************************************************************/
void main(void)
{
int X, Y, Buttons;
if (!MouseDetect()) {
fprintf(stderr, "No mouse was detected, can'nt continue\n");
MyExit(1);
}
clrscr(); /* Clear screen */
MouseInit(); /* Install Mouse */
MouseShowCursor();
gotoxy (2, 10);
printf("Press any button, or move mouse to get events. Press both buttons to exit.");
do {
while (!MouseQueryBuffer());
if (MouseGetBuffer (&X, &Y, &Buttons)) {
gotoxy(33, 15);
printf("Over Run Error");
MouseFlushBuffer();
sleep(1);
gotoxy(33, 15);
printf(" ");
}
gotoxy(20, 5);
printf("Head = %3d, Tail = %3d, Full = %3d\n",
BufferHead, BufferTail, BufferFull);
gotoxy(16, 1);
if ((Buttons & 0x01) != 0)
printf(" Left ");
else if ((Buttons & 0x02) != 0) printf("Right ");
else printf(" No ");
printf("Button was pushed at X=%-3d Y=%-3d", X, Y);
}
while ((Buttons & 0x03) != 0x03); /* Both buttons were pushed */
MouseHideCursor();
MouseClose();
clrscr(); /* Clear screen */
}
#endif DEBUG