home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * 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
-