home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / irit / drawfuns.arc / MOUSEDRV.C < prev    next >
Text File  |  1989-09-06  |  14KB  |  371 lines

  1. /*****************************************************************************
  2. * W A R N I N G : This module assumes mouse driver was installed using         *
  3. * one of the following program: mouse.com or mouse.sys.                 *
  4. *                                         *
  5. * This module can be compiled in any model (tiny..huge)                 *
  6. *                                         *
  7. * The following routines are available:                         *
  8. * 1. MouseDetect() - returns TRUE if mouse detected in system.             *
  9. * 2. MouseInit() - must be called first before any other call.             *
  10. * 3. MouseShowCorsur() - show mouse cursor.                     *
  11. * 4. MouseHideCorsur() - hide mouse cursor.                     *
  12. * 5. MouseSetPosition() - set mouse XY position.                 *
  13. * 6. MouseQueryBuffer() - returns event ring buffer status.             *
  14. * 7. MouseQueryDataBuffer() - returns event ring buffer data status.         *
  15. * 8. MouseGetBuffer() - returns next event from ring buffer.             *
  16. * 9. MouseFlushBuffer() - clear all data currently in buffer.             *
  17. * 10.MouseClose() - must be called last before application program dies.     *
  18. *                                         *
  19. * Note that as the mouse driver is used asyncronically (i.e. interrupts)     *
  20. * fail to call MouseInit() at the begining or even worse, call             *
  21. * MouseClose() in the end is an invitation for total system disaster!         *
  22. *                                         *
  23. * Written by:  Gershon Elber            IBM PC Ver 0.1,    Sep. 1988    *
  24. *****************************************************************************/
  25.  
  26. /* #define  DEBUG        /* Uncomment it for simple test routine */
  27.  
  28. #include <dos.h>
  29. #include <stdio.h>
  30. #include <graphics.h>
  31. #include "GraphGnG.h"
  32. #include "MouseDrv.h"
  33. #include "Program.h"
  34.  
  35. #ifdef   DEBUG
  36. #include <conio.h>
  37. #endif   DEBUG
  38.  
  39. /* Mouse range (start from 0) - MUST be initialized by GraphGen module!     */
  40. int MSMouseXmax = 0, MSMouseYmax = 0;
  41.  
  42. static   int MouseVectorInterrupt = 0,       /* MouseHandler vector interrupt */
  43.          BufferHead, BufferTail, BufferFull,   /* Implement ring buffer */
  44.          BufferOverRun,          /* Over run error in mouse buffer */
  45.          MouseBuffer[BUFFER_SIZE][2],         /* Mouse event to save. */
  46.          WasMouseSetUp = FALSE,  /* TRUE - mouse successfully installed */
  47.              SkipMouseEvents = 1;     /* Number of move events to skip + 1. */
  48. static   struct SREGS SRegs;
  49.  
  50. /**************************************************************************
  51. * Mouse interrupt server. Gets control each time the mouse is moved or    *
  52. * one of the buttons was pushed.                      *
  53. * I realy wanted to try the interrupt function defined in Turbo C, but    *
  54. * the mouse calls us with far call...                      *
  55. * We test 7 interrupts (060h-066h) for unused one (address is NULL) and   *
  56. * use that one to interface the interrupt TurboC routine via int 06x.     *
  57. **************************************************************************/
  58. static void far MouseInterrupt0(void) { geninterrupt (0x60); }
  59. static void far MouseInterrupt1(void) { geninterrupt (0x61); }
  60. static void far MouseInterrupt2(void) { geninterrupt (0x62); }
  61. static void far MouseInterrupt3(void) { geninterrupt (0x63); }
  62. static void far MouseInterrupt4(void) { geninterrupt (0x64); }
  63. static void far MouseInterrupt5(void) { geninterrupt (0x65); }
  64. static void far MouseInterrupt6(void) { geninterrupt (0x66); }
  65.  
  66. static void interrupt MouseHandler(void);
  67. static void MouseSysCall(int Func, int *m2, int *m3, int *m4);
  68.  
  69. /**************************************************************************
  70. * Mouse detect routine. Does three step test:                  *
  71. * 1. Test if there is none NULL vector in vector interrupt 0x33 which     *
  72. *    should hold the mouse driver.                      *
  73. * 2. Test if that pointer is pointing on IRET instruction or not.      *
  74. * 3. Test if the mouse is connected by calling to the mouse driver -      *
  75. *    sys call 0x00.                              *
  76. **************************************************************************/
  77. int MouseDetect(void)
  78. {
  79.     unsigned char far *Ptr;
  80.     union REGS Regs;
  81.  
  82.     /* Look if anything is installed in the mouse interrupt vector: */
  83.     if (((Ptr = (unsigned char far *) getvect(0x33)) ==
  84.                         (unsigned char far *) NULL) ||
  85.     (*Ptr == 0xcf /* IRET */)) return FALSE;
  86.  
  87.     Regs.x.ax = 0; /* Select reset and test function */
  88.      /* interrupt 51 decimal is used by mouse device driver itself: */
  89.     int86x(0x33, &Regs, &Regs, &SRegs);
  90.  
  91.     return (Regs.x.ax);
  92. }
  93.  
  94. /**************************************************************************
  95. * This is the mouse handler itself: called via int 06xh called from the   *
  96. * mouse driver through MouseInterruptx()...                  *
  97. * The x, y coordinates are saved as two integers in the buffer as follows:*
  98. * X is positive if Left Button is pressed, Negative otherwise.          *
  99. * Y is positive if Right Button is pressed, Negative otherwise.          *
  100. * Note 1 is added to X, Y to make them none zero...              *
  101. **************************************************************************/
  102. static void interrupt MouseHandler(void)
  103. {
  104.     static int Skip = 0;
  105.     int Buttons = _BX, X = _CX, Y = _DX;
  106.  
  107.     if (!Buttons && Skip++ < SkipMouseEvents) return;
  108.     Skip = 0;
  109.  
  110.     if (BufferFull) BufferOverRun = TRUE;        /* Buffer overflow */
  111.     else {
  112.     MouseBuffer[BufferHead][0] = (Buttons & 0x01 ? X+1 : -X-1);
  113.     MouseBuffer[BufferHead++][1] = (Buttons & 0x02 ? Y+1 : -Y-1);
  114.     if (BufferHead == BUFFER_SIZE) BufferHead = 0;
  115.     if (BufferHead == BufferTail) BufferFull = TRUE;
  116.     }
  117. }
  118.  
  119. /**************************************************************************
  120. * See all description on all functions available (0-16, 19) on page 54 in *
  121. * Microsoft Mouse manual.                          *
  122. **************************************************************************/
  123. static void MouseSysCall(int Func, int *m2, int *m3, int *m4)
  124. {
  125.     union REGS Regs;
  126.  
  127.     Regs.x.ax = Func; /* Select the requested function */
  128.     Regs.x.bx = *m2;
  129.     Regs.x.cx = *m3;
  130.     Regs.x.dx = *m4;
  131.  
  132.      /* interrupt 51 decimal is used by mouse device driver itself: */
  133.     int86x(0x33, &Regs, &Regs, &SRegs);
  134.  
  135.     *m2 = Regs.x.bx;
  136.     *m3 = Regs.x.cx;
  137.     *m4 = Regs.x.dx;
  138. }
  139.  
  140. /**************************************************************************
  141. * Mouse Initialization: return NULL if succesful, else error msg string.  *
  142. **************************************************************************/
  143. char *MouseInit(void)
  144. {
  145.     int i, m2, m3, m4;
  146.     void far *MouseIntrAddr;
  147.  
  148.     if (WasMouseSetUp) return (char *) NULL;       /* Close old init. first! */
  149.  
  150.     switch (GraphDriver) {
  151.     case CGA:
  152.     case HERCMONO:
  153.         SkipMouseEvents = 2;         /* Take every second event! */
  154.         break;
  155.     case EGA:
  156.     case EGA64:
  157.     case EGAMONO:
  158.     case VGA:
  159.         SkipMouseEvents = 4;  /* Takes too much time to redraw cursor... */
  160.         break;
  161.     }
  162.  
  163.     SRegs.ds = _DS;  /* In case the communication with the driver needs that */
  164.  
  165.     /* Search for free location in the interrupt vector in 0x60..0x66: */
  166.     for (i=0x60; i<0x67; i++) if ((void far *) NULL == getvect(i)) break;
  167.     if (i >= 0x67) {
  168.     return (char *) "Mouse Install: All interrupts in use (0x60..0x66)\n";
  169.     }
  170.     MouseVectorInterrupt = i;
  171.  
  172.     BufferHead = BufferTail = 0;            /* Reset the Buffer pointers */
  173.     BufferFull = BufferOverRun = FALSE;
  174.  
  175.     MouseSysCall(0, &m2, &m3, &m4);                /* Install Mouse */
  176.     if (MSMouseXmax == 0 || MSMouseYmax == 0) {
  177.     GGCloseGraph();                   /* Might open other device !? */
  178.     fprintf(stderr,
  179.         "MouseInit: Mouse range was not initialized by graphic driver\n");
  180.     MyExit(1);
  181.     }
  182.     m3 = 0;
  183.     m4 = MSMouseXmax;
  184.     MouseSysCall(7, &m2, &m3, &m4);             /* Set Column Range */
  185.     m3 = 0;
  186.     m4 = MSMouseYmax;
  187.     MouseSysCall(8, &m2, &m3, &m4);                /* Set Row Range */
  188.     m3 = (int) (16 / (((double) MSMouseXmax) / 1000));
  189.     m4 = (int) (8 / (((double) MSMouseYmax) / 1000));
  190.     MouseSysCall(15, &m2, &m3, &m4);         /* Set Mickeys Per 8 pixels */
  191.  
  192.     setvect(MouseVectorInterrupt, MouseHandler);  /* Link the MouseHandler */
  193.     switch (MouseVectorInterrupt) {
  194.     case 0x60: MouseIntrAddr = MouseInterrupt0; break;
  195.     case 0x61: MouseIntrAddr = MouseInterrupt1; break;
  196.     case 0x62: MouseIntrAddr = MouseInterrupt2; break;
  197.     case 0x63: MouseIntrAddr = MouseInterrupt3; break;
  198.     case 0x64: MouseIntrAddr = MouseInterrupt4; break;
  199.     case 0x65: MouseIntrAddr = MouseInterrupt5; break;
  200.     case 0x66: MouseIntrAddr = MouseInterrupt6; break;
  201.     }
  202.     m3 = 0x0b;/* Set bits 0, 1, 3 - interrupt on mouse move & button pressed */
  203.     m4 = FP_OFF(MouseIntrAddr);
  204.     SRegs.es = FP_SEG(MouseIntrAddr);
  205.     MouseSysCall(12, &m2, &m3, &m4); /* Link the MouseInterruptx() routine */
  206.  
  207.     WasMouseSetUp = TRUE;
  208.  
  209.     return (char *) NULL;
  210. }
  211.  
  212. /**************************************************************************
  213. * Mouse Closing:                              *
  214. **************************************************************************/
  215. void MouseClose(void)
  216. {
  217.     int m2, m3, m4;
  218.  
  219.     if (!WasMouseSetUp) return;                 /* Install mouse first! */
  220.  
  221.     m3 = 0x00;                    /* No interrupts any more... */
  222.     MouseSysCall(12, &m2, &m3, &m4);
  223.  
  224.     /* Clear that interrupt vector for other uses... */
  225.     setvect(MouseVectorInterrupt, (void interrupt (*)()) NULL);
  226.  
  227.     WasMouseSetUp = FALSE;
  228. }
  229.  
  230. /**************************************************************************
  231. * Routine returns TRUE if buffer is not empty.                  *
  232. **************************************************************************/
  233. int MouseQueryBuffer(void)
  234. {
  235.     return (BufferFull || BufferHead != BufferTail);
  236. }
  237.  
  238. /**************************************************************************
  239. * Routine to return Mouse buffer status:                  *
  240. * Returns TRUE if buffer is not empty. In addition sets X, Y, Buttons to  *
  241. * the end of buffer without modifying the buffer, and set OverRunError.      *
  242. **************************************************************************/
  243. int MouseQueryDataBuffer(int *X, int *Y, int *Buttons, int *OverRunError)
  244. {
  245.     if (BufferFull || BufferHead != BufferTail) {
  246.     *X = ABS(MouseBuffer[BufferTail][0]) - 1;
  247.     *Y = ABS(MouseBuffer[BufferTail][1]) - 1;
  248.     *Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
  249.            (MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
  250.     *OverRunError = BufferOverRun;
  251.     return TRUE;
  252.     }
  253.     else return FALSE;
  254. }
  255.  
  256. /**************************************************************************
  257. * Routine to get one event from buffer. waits for one if buffer empty.    *
  258. * Returns OverRun status - TRUE if over run occurs. In addition sets      *
  259. * X, Y, Buttons to the end of buffer, and increment.              *
  260. **************************************************************************/
  261. int MouseGetBuffer(int *X, int *Y, int *Buttons)
  262. {
  263.     /* Wait for event if buffer is empty: */
  264.     while (!(BufferFull || BufferHead != BufferTail));
  265.  
  266.     *X = ABS(MouseBuffer[BufferTail][0]) - 1;
  267.     *Y = ABS(MouseBuffer[BufferTail][1]) - 1;
  268.     *Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
  269.            (MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
  270.  
  271.     disable();                           /* No interrupts now! */
  272.     if (BufferHead == BufferTail) BufferFull = FALSE;
  273.     if (++BufferTail == BUFFER_SIZE) BufferTail = 0;
  274.     enable();                          /* interrupts o.k. now */
  275.  
  276.     return BufferOverRun;
  277. }
  278.  
  279. /**************************************************************************
  280. * Routine to flush and clear all the mouse event buffer.          *
  281. **************************************************************************/
  282. void MouseFlushBuffer(void)
  283. {
  284.     disable();                           /* No interrupts now! */
  285.     BufferHead = BufferTail;
  286.     BufferFull = BufferOverRun = FALSE;
  287.     enable();                          /* interrupts o.k. now */
  288. }
  289.  
  290. /**************************************************************************
  291. * Mouse Show Cursor:                              *
  292. **************************************************************************/
  293. void MouseShowCursor(void)
  294. {
  295.     int m2, x, y;
  296.  
  297.     MouseSysCall(1, &m2, &x, &y); /* Show cursor */
  298. }
  299.  
  300. /**************************************************************************
  301. * Mouse Hide Cursor:                              *
  302. **************************************************************************/
  303. void MouseHideCursor(void)
  304. {
  305.     int m2, x, y;
  306.  
  307.     MouseSysCall(2, &m2, &x, &y);                  /* Hide cursor */
  308. }
  309.  
  310. /**************************************************************************
  311. * Mouse Set Position:                              *
  312. **************************************************************************/
  313. void MouseSetPosition(int X, int Y)
  314. {
  315.     int dummy;
  316.  
  317.     MouseSysCall(4, &dummy, &X, &Y);                 /* Set position */
  318. }
  319.  
  320. #ifdef DEBUG
  321.  
  322. /**************************************************************************
  323. * Simple test routine:                              *
  324. **************************************************************************/
  325. void main(void)
  326. {
  327.     int X, Y, Buttons;
  328.  
  329.     if (!MouseDetect()) {
  330.     fprintf(stderr, "No mouse was detected, can'nt continue\n");
  331.     MyExit(1);
  332.     }
  333.  
  334.     clrscr();     /* Clear screen */
  335.     MouseInit(); /* Install Mouse */
  336.     MouseShowCursor();
  337.  
  338.     gotoxy (2, 10);
  339.     printf("Press any button, or move mouse to get events. Press both buttons to exit.");
  340.  
  341.     do {
  342.     while (!MouseQueryBuffer());
  343.     if (MouseGetBuffer (&X, &Y, &Buttons)) {
  344.         gotoxy(33, 15);
  345.         printf("Over Run Error");
  346.         MouseFlushBuffer();
  347.         sleep(1);
  348.         gotoxy(33, 15);
  349.         printf("              ");
  350.     }
  351.  
  352.     gotoxy(20, 5);
  353.     printf("Head = %3d, Tail = %3d, Full = %3d\n",
  354.                 BufferHead, BufferTail, BufferFull);
  355.  
  356.     gotoxy(16, 1);
  357.         if ((Buttons & 0x01) != 0)
  358.          printf(" Left ");
  359.         else if ((Buttons & 0x02) != 0) printf("Right ");
  360.          else printf("   No ");
  361.         printf("Button was pushed at X=%-3d  Y=%-3d", X, Y);
  362.     }
  363.     while ((Buttons & 0x03) != 0x03);         /* Both buttons were pushed */
  364.  
  365.     MouseHideCursor();
  366.     MouseClose();
  367.     clrscr();                             /* Clear screen */
  368. }
  369.  
  370. #endif  DEBUG
  371.