home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / MPP400 / MOUSE.DOC < prev    next >
Text File  |  1992-10-07  |  50KB  |  1,214 lines

  1.  
  2.                           Mouse++ Version 4.0
  3.  
  4.                   Copyright (c)1992 by Carl Moreland
  5.                                10/06/92
  6.  
  7. -----------------------------------------------------------------------
  8.  
  9. Using the Mouse Class
  10.  
  11.     To  incorporate  the  mouse routines in your  program,  simply  add
  12. mouse.lib to your project or make file and #include mouse.h in any  mo-
  13. dule that calls a mouse function.  mouse.lib contains all the functions
  14. in mouse.cpp and cgc.cpp,  but the functions are separated into differ-
  15. ent object modules for greater efficiency.  Note that mouse.lib is com-
  16. piled for the large memory model.
  17.  
  18.     An instance of the Mouse class (there can only be ONE instance)  is 
  19. declared as extern in mouse.h,  so any file that #includes mouse.h will 
  20. automatically have access to the mouse.  You should NOT declare an  in-
  21. stance of the Mouse class in any part of your program. If you intend to
  22. change the mouse cursor, then you also need to #include cursor.h.
  23.  
  24.     When you link the mouse code into your program,  an instance of the
  25. mouse class is declared:
  26.  
  27.     Mouse mouse;
  28.  
  29. The  constructor Mouse::Mouse() calls the mouse driver  reset  function
  30. (all mouse driver functions are called via interrupt 33h)  and  initia-
  31. lizes  the flags exists, enabled, and visible.  exists is set to 1 if a
  32. mouse  was  found and should be checked first.  All other  mouse  class
  33. functions check exists before issuing interrupt 33h calls and abort  if
  34. it  is zero.  enabled is initially zero meaning the mouse is  disabled,
  35. and  visible is used by Show() and Hide() to keep track of  the  cursor
  36. visibility. An example of initializing the mouse is:
  37.  
  38.     #include "mouse.h"
  39.  
  40.     main()
  41.     {
  42.       if(mouse.Exists())        // check for mouse
  43.       {
  44.         mouse.Enable();        // enable the mouse
  45.         mouse.Show();        // display the cursor
  46.         ...
  47.       }
  48.     }
  49.  
  50. Again,  including  mouse.h automatically creates  an  instance  of  the
  51. class, so all you have to do is start using it.
  52.  
  53.     Once  the  mouse is initialized,  it may be necessary to  set  some
  54. parameters based on what video mode is being used. Strangely, the mouse
  55. driver  uses  pixel coordinates for both text and graphics  mode,  with
  56. (0,0)  being  the upper left hand corner of the screen,  and  (639,199)
  57. being  the default lower right hand corner.  This would be correct  for
  58. CGA graphics mode and for normal 80x25 text mode - for text mode,  this
  59. means that each character cell is treated as an 8x8 pixel array. If you
  60. are programming for the EGA or VGA as is the norm these days,  you will
  61. want  to change the y-limit of 199 for high resolution graphics and  43
  62. or 50 line text modes.  Failure to do this means that the mouse  cursor
  63. will not move below the 200th line in graphics mode, or the 25th row in
  64. text mode.  (Older mouse drivers might not support more than 200 lines.
  65. If  this is the case,  you will need to update your mouse driver.)  For
  66. 640x480 VGA graphics, you need to set the y-limit to (0,479) by calling
  67. yLimit(0,479).  For  43 or 50 line text mode,  the mouse  driver  still
  68. treats  each character cell as an 8x8 pixel array,  so you need to  set
  69. the  y-limit  to (0,349) or (0,399), respectively.  Since  the  default
  70. width  of 640 pixels is correct for most video modes,  xLimit() is only
  71. necessary  when using SuperVGA graphics.  (See the section on  SuperVGA
  72. support) Both xLimit() and yLimit() can also be used to limit the mouse
  73. cursor to a small portion of the screen, such as a menu.
  74.  
  75.     You  may want to use a mouse cursor other than the default  cursor.
  76. To do this,  call the function SetCursor() with the appropriate  cursor
  77. name.  Many programs (especially graphics) will use  several  different
  78. cursors  depending on the location of the mouse (such as an  arrow  for
  79. menus  and  an i-beam for text) or the particular function  being  pro-
  80. cessed (such as an hourglass for wait).  Several cursors are predefined
  81. in the file cursor.h.  To use them,  simply include this header file in
  82. whatever  module changes the cursor.  For more information on  cursors,
  83. see the Mouse Cursors section.
  84.  
  85.     Finally,  you may want to set the motion parameters,  which include
  86. the  mickey-to-pixel ratio and the double-speed threshold.  The mickey-
  87. to-pixel  ratio  is set by MickToPix() and defines how many mickeys  it
  88. takes  to move the mouse 8 pixels.  (A mickey is single count of  mouse
  89. motion. Most mice are 200 "dots-per-inch", which means that one inch of
  90. movement  results in 200 mickeys.)  If both the x and y parameters  are
  91. set  to 8,  then there will be a one-to-one correlation  between  mouse
  92. motion  and cursor motion.  The default values are 8 in the  horizontal
  93. direction and 16 for the vertical.  The vertical value of 16 means  the
  94. mouse must be moved twice as far vertically as horizontally to  get the
  95. same cursor movement.  This is fine for text mode where the  equivalent
  96. screen  resolution  of 640x200 results in an  equivalent  pixel  aspect
  97. ratio of 2.4-to-1.  In EGA/VGA graphics mode the y-direction will  seem
  98. noticeably  slower,  particularly for 640x480 which has  an  equivalent
  99. pixel  aspect ratio of 1-to-1.  A vertical ratio of 8 will  cure  this.
  100. The lower the ratio, the farther the cursor will move for a given mouse
  101. movement.  Setting either ratio lower than 8 means that the cursor can-
  102. not be located on every pixel. For example, setting the ratio to 4 will
  103. cause  the cursor to move 2 pixels for every mickey.  The  double-speed
  104. threshold  is set by a call to SetSpeedThreshold().  When the speed  of
  105. the mouse (in mickeys per second) exceeds the speed parameter passed to
  106. SetSpeedThreshold(), the motion speed of the cursor will double. A com-
  107. plete initialization might look like this:
  108.  
  109.     #include "mouse.h"
  110.     #include "cursor.h"
  111.  
  112.     main()
  113.     {
  114.       { initialize screen };
  115.       if(mouse.Exists())
  116.       {
  117.         mouse.SetCursor(cross);
  118.         mouse.yLimit(0,479);    // VGA 640x480
  119.         mouse.MickToPix(8,8);
  120.         mouse.SetSpeedThreshold(32);
  121.         mouse.Enable();
  122.         mouse.Show();
  123.         ...
  124.       }
  125.     }
  126.  
  127.     The  mouse should be reset before your program terminates  so  that
  128. the  calling program does not inherit any strange parameters.  This  is
  129. particularly true of the event handler. Because it is an interrupt rou-
  130. tine,  failure to reset the mouse could lead to a system crash  if  the
  131. handler is still pointing to the address of what used to be your  hand-
  132. ler routine. The destructor Mouse::~Mouse() first resets the mouse sta-
  133. tus by calling function 00h, and then restores the original event hand-
  134. ler with function 14h.
  135.  
  136. -----------------------------------------------------------------------
  137.  
  138. Reading the Mouse
  139.  
  140.     Most  of the standard mouse functions stuff any return  values  di-
  141. rectly  into the class variables and have a return type void.  This  is
  142. because many mouse functions return more than one item of  information.
  143. You  can then use the appropriate inline function to read the  required
  144. private  variable.  To check for the mouse position, for instance,  you
  145. would call Position() followed by either x() or y(), or both, such as:
  146.  
  147.     for(;;)
  148.     {
  149.       mouse.Position();
  150.       if(mouse.x() > 320 || mouse.y() > 100)
  151.         do_something();
  152.     }
  153.  
  154. This  method has the advantage of capturing both the x and y  positions
  155. with  a single function call,  and those variables can then be read  at
  156. your  leisure.  However,  we generally don't care where  the  mouse  is
  157. located  unless  a button event that we are looking for  has  occurred.
  158. Position() also returns the status of the mouse buttons, so we can also
  159. check them:
  160.  
  161.     for(;;)
  162.     {
  163.       mouse.Position();
  164.       if(mouse.LB_Dn())        // check for left button down
  165.       {
  166.         if(mouse.x() > 320 || mouse.y() > 100)
  167.           do_something();
  168.       }
  169.       else
  170.         do_something_else();
  171.     }
  172.  
  173. This  loop will continuously check to see if the left button  has  been
  174. pressed.  If the do_something_else() code is slow then there is a  pos-
  175. sibility  that a button press could be missed since Position()  returns
  176. the  real-time status of the mouse.  That is, during execution  of  the
  177. do_something_else()  code,  the mouse button could be pressed  and  re-
  178. leased and Position() would not capture it. The functions Pressed() and
  179. Released() are best suited for checking for a button event because they
  180. will return the button status since the last time they were called. For
  181. example, this code
  182.  
  183.     for(;;)
  184.     {
  185.       if(mouse.Pressed(LEFTBUTTON))
  186.       {
  187.         if(mouse.x() > 320 || mouse.y() > 100)
  188.         do_something();
  189.       }
  190.       else
  191.         do_something_else();
  192.     }
  193.  
  194. is guaranteed to capture a button press even if the do_something_else()
  195. code is slow to execute. Since Pressed() and Released() also return the
  196. cursor position, a separate call to Position() is not necessary.
  197.  
  198.     In using the mouse,  it is often necessary to know if the cursor is
  199. located  within a certain area of the screen.  For example,  in a  menu
  200. interface,  you want to know if the cursor is located on a menu  selec-
  201. tion  when a mouse button is clicked.  The function InBox()  adds  this
  202. capability.  The parameters passed describe the upper  left  and  lower
  203. right corners of the box. The return value is 1 if the cursor is in the
  204. box, 0 if not. Therefore, the code
  205.  
  206.     if(mouse.InBox(40,40,100,100))
  207.  
  208. will  be true if the mouse cursor is in a box with corners (40,40)  and
  209. (100,100). Like other mouse functions, the coordinates are pixels, even
  210. if the screen is in text mode.
  211.  
  212.     In some cases you may want to hide the cursor if it falls inside  a
  213. certain area.  The mouse driver provides such a function which,  in  my
  214. opinion, has two drawbacks. Function 10h defines an exclusion window in
  215. which  the mouse cursor will turn itself off.  However,  the programmer
  216. must  then manually turn the cursor back on once it is outside the  ex-
  217. clusion area,  and this requires continuously checking the mouse  posi-
  218. tion, such as:
  219.  
  220.     for(;;)
  221.     {
  222.       mouse.Exclude(40,40,100,100);
  223.       do_some_processing();
  224.       if(!mouse.InBox(40,40,100,100))
  225.         mouse.show();
  226.     }
  227.  
  228. The  other problem with function 10h is that it only looks at  the  hot
  229. spot  when checking the cursor's position, so part of the cursor  could
  230. enter the exclusion area before the hot spot. The whole point of defin-
  231. ing  an exclusion area is to turn the cursor off if it enters  the  de-
  232. fined area. The Mouse++ Exclude() function is based on the InBox() fun-
  233. ction, taking into account the hot spot location,  cursor image  height
  234. and width, and cursor visibility.
  235.  
  236.     Finally,  if  your program is performing a time-consuming  task  in
  237. which mouse input is not needed, you may want to disable the mouse.  If
  238. the  mouse  is not disabled,  the user might become frustrated  with  a
  239. mouse  that does not respond, and the event buffer could become  filled
  240. with useless events. Calling the function Disable() will turn the mouse
  241. off and disable the interrupt handler. The mouse and interrupt  handler
  242. are re-enabled with the next call to Enable(),  although the mouse cur-
  243. sor must be turned on with an explicit call to Show():
  244.  
  245.     ...
  246.     mouse.Disable();
  247.     do_some_long_processing();
  248.     mouse.Enable();
  249.     mouse.Show();
  250.     ...
  251.  
  252. -----------------------------------------------------------------------
  253.  
  254. Mouse Cursors
  255.  
  256.     Mouse++ currently supports standard text and graphics cursors,  and
  257. has rudimentary support for ColorGraphicsCursors. The mouse cursor type
  258. and  shape are set by the function SetCursor().  In graphics mode,  the
  259. cursor  is initially set to the familiar upper left pointing  arrow  by
  260. the  mouse driver.  A standard graphics cursor is up to 16x16 pixels in
  261. size  and moves in single pixel increments.  It is defined by a  screen
  262. mask  (background),  an overlying cursor mask (foreground),  and a  hot
  263. spot. Since the cursor is 16x16 pixels, a single-pixel hot spot must be
  264. defined so that a unique pixel position can be determined for the  cur-
  265. sor. The hot spot has x and y values with valid ranges of 0 to 15.
  266.  
  267.     The two masks determine how the screen will appear where the cursor
  268. is located.  The screen mask is first ANDed with the screen pixels, and
  269. the  cursor mask is then XORed with the resulting screen.  If a  screen
  270. mask bit is 0 it will set the underlying screen pixel to 0 (black), and
  271. if  the screen mask bit is 1 the pixel color will not change.  A cursor
  272. mask bit of 0 does nothing, and a cursor mask bit of 1 will invert  the
  273. underlying pixel color.  Since the masks have only values of 1 or 0 for
  274. each  pixel  location,  but each pixel can have  a  color,  you  cannot
  275. achieve  complete control of the cursor color using a standard  cursor.
  276. The  two  basic choices are a black and white cursor where  the  screen
  277. mask bits are 0,  or a cursor that inverts the screen colors where  the
  278. screen mask bits are 1.
  279.  
  280.     Figure 1  shows the default cursor as an example.  The screen  mask
  281. alone will set the screen pixels to black for the bits that are 0, cre-
  282. ating a black arrow.  The cursor mask bits that are 1 will then  invert
  283. the screen color, meaning part of the black arrow will become white. If
  284. you lay the cursor mask directly over the screen mask,  you will notice
  285. that  the  screen mask arrow extends one pixel beyond the  cursor  mask
  286. arrow.  Because a screen mask bit 0 will create a black background  for
  287. the cursor mask, this has the effect of putting a one pixel black  bor-
  288. der around the cursor.  The reason for doing this is to make the cursor
  289. visible  even where the screen background is white.  Making the  screen
  290. mask  bits all 1's so that the cursor XOR's with the underlying  screen
  291. is  useful in creating a CAD cursor (such as a "+" or a "x") that  must
  292. be  one pixel wide.  The best way to get a better understanding of  the
  293. graphics cursor is to try some out.  cursor.h defines several  graphics
  294. cursors.
  295.  
  296. -----------------------------------------------------------------------
  297.  
  298.     0011111111111111    0000000000000000
  299.     0001111111111111    0100000000000000
  300.     0000111111111111    0110000000000000
  301.     0000011111111111    0111000000000000
  302.     0000001111111111    0111100000000000
  303.     0000000111111111    0111110000000000
  304.     0000000011111111    0111111000000000
  305.     0000000001111111    0111111100000000
  306.     0000000000111111    0111111110000000
  307.     0000000000011111    0111111111000000
  308.     0000000111111111    0111110000000000
  309.     0001000011111111    0100011000000000
  310.     0011000011111111    0000011000000000
  311.     1111100001111111    0000001100000000
  312.     1111100001111111    0000001100000000
  313.     1111110000111111    0000000110000000
  314.  
  315.       Screen Mask          Cursor Mask
  316.  
  317. Figure 1: Example graphics cursor
  318. -----------------------------------------------------------------------
  319.  
  320.     The  graphics mask pair are defined together in a single  array  of
  321. type unsigned integer.  For clarity,  comment fields were added in cur-
  322. sor.h to show what the masks will actually produce. This is helpful not
  323. only in identifying what a cursor looks like, but also in designing new
  324. cursors.  The GraphicsCursor class constructor is used for declaring  a
  325. cursor.  It takes as arguments the cursor hot spot,  mask array,  width
  326. and height. The width and height are the actual pixel dimensions of the
  327. image.  In Figure 1,  the width is 11 and the height is 16 -  these are
  328. the  maximum  dimensions of the defined screen mask,  even  though  the
  329. overall array is 16x16.  An instance of GraphicsCursor can be passed to
  330. SetCursor() to make it the current cursor.
  331.  
  332.     SetCursor() can also set the text cursor type and shape.  There are
  333. two  cursor types in text mode.  The hardware cursor places the  normal
  334. video  cursor (the cursor normally associated with the keyboard)  under
  335. the  control of the mouse.  The software cursor is independent  of  the
  336. video cursor and behaves similarly to the graphics cursor. The software
  337. cursor is used in most applications so that the user is presented  with
  338. the  normal video cursor for typing and a mouse cursor for menu  selec-
  339. tion, etc.  The cursor type - 0 for software, 1 for hardware - is  part
  340. of the TextCursor class.
  341.  
  342.     Like the graphics cursor,  the text software cursor also requires a
  343. screen and cursor mask,  but no hot spot since the cursor always  takes
  344. up  a  whole character cell,  regardless of where the mouse  cursor  is
  345. actually positioned in that cell. (If a hardware cursor is implemented,
  346. the  starting  and ending scan lines for the cursor are required.)  The
  347. two  masks operate only on a character cell,  not a 16x16 pixel  array.
  348. Each cell consists of a one-byte character value and a one-byte charac-
  349. ter attribute (which sets the foreground and background colors), so the
  350. masks must each be two bytes long.  The upper byte masks the attribute,
  351. and  the lower byte masks the character.  Like the graphics masks,  the
  352. screen mask is XORed with the underlying character cell, and the cursor
  353. mask is ANDed with the resulting value.  The difference is that in text
  354. mode, both the character value and its color can be changed, whereas in
  355. graphics mode, the pixel colors cannot be controlled.
  356.  
  357.     To get a better understanding of what the masks will do, we need to
  358. look at an example of a screen character:
  359.  
  360.       6B24h = 0110 1011 0010 0100 b
  361.               |--- ---- ---------
  362.               | |   |       |__ character value  (24h)
  363.               | |   |__________ foreground color (11d)
  364.               | |______________ background color (6d)
  365.               |________________ blinking bit (1=blinking)
  366.  
  367. This  value will display a '$' (24h) with a background color  of  brown
  368. (6) and a foreground color of lightcyan (11).  With the text cursor, we
  369. can  mask each bit of the character and attribute,  so not only can  we
  370. set the mouse cursor character,  but we can also control the foreground
  371. and background colors (and even blinking).  The cursor masks default to
  372. a reverse box, which is
  373.  
  374.     Screen Mask = 77FFh = 0111 0111 1111 1111 b
  375.     Cursor Mask = 7700h = 0111 0111 0000 0000 b
  376.  
  377. The first byte of the screen mask,  77h in this example,  is ANDed with
  378. the  underlying characters attribute.  The first 7h is ANDed  with  the
  379. background  color  so that all colors but the blinking bit  are  passed
  380. through.  Masking the blinking bit to 0 will allow the mouse cursor  to
  381. rest on a blinking character without itself blinking.  The second 7h is
  382. ANDed  with the foreground color so that those colors are also  passed,
  383. except  that the high intensity colors will be converted to low  inten-
  384. sity. The FFh also passes the screen character. In the cursor mask, the
  385. 77h  will invert both the foreground and background colors,  while  the
  386. 00h  creates an "empty" character, which is a character cell  with  no-
  387. thing in it (a box).
  388.  
  389.     If  you  want to create a cursor with a  particular  character  and
  390. color,  you would set the screen mask to 0000h and the cursor  mask  to
  391. whatever color and character values desired.  For example,
  392.  
  393.     Screen Mask = 0000h = 0000 0000 0000 0000b
  394.     Cursor Mask = 0F23h = 0000 1111 0010 0011b
  395.  
  396. will set the cursor character to a '#' with a background color of black
  397. and a foreground color of white.  More complex combinations are  possi-
  398. ble,  such as setting the cursor's foreground color to a constant value
  399. but allowing the screen's background color to show through.  Again, the
  400. best  way to understand it is to try it,  and cursor.h defines  several
  401. text cursors.
  402.  
  403.     In graphics mode, the mouse driver takes care of drawing the cursor
  404. and restoring the image under the cursor when it moves. One drawback to
  405. this  is that you cannot use color cursors in graphics mode  using  the
  406. mouse driver. You can instead create a color image, manually draw it to
  407. the screen, and manually restore the underlying image.  This is exactly
  408. how  the  ColorGraphicsCursors work.  If a CGC is installed  using  the
  409. SetCursor()  command,  then the special drawing functions will  trigger
  410. off of the event handler, thereby drawing the cursor whenever the mouse
  411. moves. CGC cursors are defined just like standard graphics cursors, ex-
  412. cept that the screen mask is split into the four video bit planes.  See
  413. cursor.h for examples.
  414.  
  415.     The color drawing functions in cgc.cpp were written purely in  C++,
  416. with no assembly language.  The reason for this was to clearly show how
  417. the  methods work.  The results are that the color cursor image  has  a
  418. slight flicker, but overall the speed is acceptable.  Also, these func-
  419. tions do not make any attempt to save and restore the video card state.
  420. This could be a problem because the drawing functions are triggered  by
  421. the  mouse event handler and could therefore be activated at any  time,
  422. even  during another graphics draw.  You can avoid problems by  turning
  423. the cursor off (using Hide()) before drawing any graphics,  which is  a
  424. good  idea anyway.  Finally, these functions only support standard  EGA
  425. and VGA resolutions.
  426.  
  427.     A  better method is to use your favorite graphics library  to  draw
  428. the cursor and restore the screen.  This will probably result in better
  429. speed and might also support higher resolutions such as  SuperVGA/VESA.
  430. (This approach also solves another drawback of the mouse drivers - they
  431. also do not support high-res modes.) To implement another graphics  li-
  432. brary, you need only modify the VideoRead(), VideoWrite(),  and Cursor-
  433. Write() funtions. An example using the BGI is provided in cgc_bgi.cpp.
  434.  
  435. -----------------------------------------------------------------------
  436.  
  437. The Event Handler
  438.  
  439.     There is another way to capture mouse events. The mouse event hand-
  440. ler  is  similar to a TSR program in that it can be set up  to  capture
  441. events in background.  The handler can be set to trigger off any combi-
  442. nation of mouse events (Table 1),  and can then execute any user  code,
  443. providing it does not issue a DOS or I/O call.  However, since the main
  444. program  is suspended during the event handler execution,  the  handler
  445. code  should  be fast so it does not to noticeably slow down  the  main
  446. program.  When an event occurs,  certain mouse information is automati-
  447. cally  placed  in the registers for the handler to  use.  The  function
  448. Save() can be used to stuff these parameters into the event buffer  for
  449. later use.  Any event handler routines you write must be declared as an
  450. interrupt type and terminate with a far return.  The macro  EventExit()
  451. provides  the proper exit code and should be the last statement in  the
  452. handler function:
  453.  
  454.     void interrupt lb_handler()
  455.     {
  456.       mouse.Save();
  457.       do_something();
  458.       EventExit();
  459.     }
  460.  
  461.     You  can then use this function and an event mask to create an  in-
  462. stance of a MouseEventHandler.  Installing it is accomplished  with the
  463. function InstallHandler():
  464.  
  465.     #include "mouse.h"
  466.  
  467.     void interrupt lb_handler();
  468.  
  469.     main()
  470.     {
  471.       unsigned char eventmask = LB_PRESSED | LB_RELEASED;
  472.           MouseEventHandler myHandler(eventmask, lb_handler);
  473.  
  474.       if(mouse.Exists())
  475.       {
  476.         mouse.InstallHandler(myHandler);
  477.         mouse.Enable();
  478.         mouse.Show();
  479.         ...
  480.       }
  481.     }
  482.  
  483. eventmask determines which mouse events will trigger the event handler.
  484. In the example above, the handler will execute whenever the left button
  485. is  pressed or released.  Because the event handler should be  kept  as
  486. small  as possible,  you normally only want to call Save() for  storing
  487. the mouse information and then exit.  The MouseEventHandler class  pro-
  488. vides  such a handler by default if you do not specify a handler  func-
  489. tion name:
  490.  
  491.     main()
  492.     {
  493.           MouseEventHandler myHandler(LB_PRESSED | LB_RELEASED);
  494.  
  495.       if(mouse.Exists())
  496.       {
  497.         mouse.InstallHandler(myHandler);
  498.  
  499.          // Here's another way of doing it:
  500.      // mouse.InstallHandler(LB_PRESSED | LB_RELEASED);
  501.  
  502.         mouse.Enable();
  503.         mouse.Show();
  504.         ...
  505.       }
  506.     }
  507.  
  508. There  might be some cases where you want the handler to do more,  such
  509. as when the program is waiting for user input and not doing much  other
  510. processing.  In such cases you may want to load different handlers, de-
  511. pending on what the program is doing.  A more functional handler can be
  512. loaded for pulldown menus, for instance,  and a bare-bones handler  (or
  513. none  at all) can be installed in speed critical areas where the  mouse
  514. has little use.
  515.  
  516.     The  Save() function called by the event handler stores  the  mouse
  517. information in a buffer instead of writing it directly into the  class.
  518. This allows events to be captured even while your program is busy doing
  519. something else.  (The keyboard has a similar buffer that provides type-
  520. ahead capability.)  Save() also calls the ColorGraphicsCursor funtions,
  521. so  if you are using CGC's and also want to define custom  event  hand-
  522. lers, you will need to consider this.  To get the event information out
  523. of the buffer, you must call the function GetEvent():
  524.  
  525.     for(;;)
  526.     {
  527.       mouse.GetEvent();        // get an event from the buffer
  528.       if(mouse.LB_Dn())        // check for left button down
  529.       {
  530.         if(mouse.x() > 320 || mouse.y() > 100)
  531.           do_something();
  532.       }
  533.       else
  534.         do_something_else();
  535.     }
  536.  
  537.     When using the event handler you also have access to two other fea-
  538. tures: MultiClick detection and the Repeater.  MultiClicks occur when a
  539. mouse button is rapidly clicked more than once. You can set up the but-
  540. tons  for MultiClicks by calling the SetClickThreshold()  function  and
  541. then check them with the DoubleClick() and MultiClick() functions:
  542.  
  543.         mouse.SetClickThreshold(250);    // set threshold to 250ms
  544.  
  545.     for(;;)
  546.     {
  547.       mouse.GetEvent();
  548.  
  549.       if(mouse.DoubleClick(LEFTBUTTON))    // check for 2 clicks
  550.         do_something();
  551.  
  552.       if(mouse.MultiClick(LEFTBUTTON) == 3)    // check for 3 clicks
  553.         do_something_else();
  554.     }
  555.  
  556. When  using this feature, you should realize that multiple clicks  will
  557. load  the buffer with several PRESSED and RELEASED events.  The  Multi-
  558. Click  buffer does not get updated until a call to  GetEvent()  occurs.
  559. Therefore,  it will take three passes through the loop above  before  a
  560. triple click shows up. If the do_something() routine for a double click
  561. clears the mouse buffer,  then the do_something_else() code will  never
  562. execute because a triple click will never occur.
  563.  
  564.     The Repeater allows a button to be pressed and held down to  gener-
  565. ate multiple PRESSED events,  much like the keyboard does.  This  would
  566. typically be used for a scrollbar routine.  Unlike the MultiClick  fea-
  567. ture,  the  Repeater  can be set up for  individual  buttons.  Use  the
  568. SetRepeatRate() function to set up the Repeater,  and then simply check
  569. for events:
  570.  
  571.     // This will set the intial delay to 250ms and the repeat rate
  572.         // to 100ms for the left button:
  573.  
  574.         mouse.SetRepeatRate(LEFTBUTTON, 250, 100);
  575.  
  576.     for(;;)
  577.     {
  578.       mouse.GetEvent();
  579.  
  580.       if(mouse.LB_Dn())
  581.         do_something();
  582.     }
  583.  
  584. The mouse class installs the Repeater by hooking it to the system clock
  585. interrupt which is called every 18ms.
  586.  
  587.     Properly  used,  event handlers can add a whole new  dimension to a
  588. mouse  driven interface.  However, there are some pitfalls to avoid. If
  589. you set the event mask to trigger on mouse movement,  then the  handler
  590. will execute quite often (every time the mouse is moved) and could  no-
  591. ticeably  slow program execution during periods of  heavy  computation.
  592. Reasons  to trigger on movement include updating a motion counter  such
  593. as in the demo program,  having cursors that dynamically change  depen-
  594. ding on the cursor position such as in a GUI,  or when using CGC's.  As
  595. mentioned before, the handler should not issue a DOS, ROM, or I/O call.
  596. The handler,  like a TSR,  is an interrupt routine that runs while  the
  597. main DOS program is suspended.  DOS is not a re-entrant operating  sys-
  598. tem  and issuing such a call will usually crash the system.  Also, some
  599. standard C library routines make use of these system functions (such as 
  600. printf()), so often the only way of finding out is by trial and reboot.
  601.  
  602. -----------------------------------------------------------------------
  603.     0x01    MOUSE_MOVED
  604.     0x02    LB_PRESSED
  605.     0x04    LB_RELEASED
  606.     0x08    RB_PRESSED
  607.     0x10    RB_RELEASED
  608.     0x20    CB_PRESSED
  609.     0x40    CB_RELEASED
  610.  
  611.     Table 1: Mouse events
  612. -----------------------------------------------------------------------
  613.  
  614. A Demonstration
  615.  
  616.     demo.cpp  is a demo program that utilizes most of the  mouse  func-
  617. tions described.  main() installs the event handler,  runs a text  mode
  618. demo, and a graphics mode demo.  The event mask is FFh which will trig-
  619. ger the handler on any mouse event. Since that includes mouse movement,
  620. the default handler that only calls Save() is used to store the parame-
  621. ters and keep execution time to a minimum.
  622.  
  623.     Both  demos  (textdemo() and graphicdemo()) call  a  function  that
  624. draws the screen and another that processes mouse events.  textscreen()
  625. assumes  a  color video card and draws a screen  with  eight  different
  626. characters and colors to demonstrate how the cursor masks work.  Notice
  627. that  the loop that draws the screen actually writes 50 lines of  video
  628. even though the demo starts out with 25 lines.  A graphical representa-
  629. tion  of a three-button mouse is drawn to show the cursor position  and
  630. button status. After calling textscreen(), textdemo() prints the infor-
  631. mation from the mouse.Info structure to the screen.  The mouse  y-limit
  632. is  set to full screen (25 lines, which is the default) and the  cursor
  633. is turned on with Show().  nexttdemo() is the processing loop for  text
  634. mode  and is called with the name of text cursor structure and a  title
  635. string.  nexttdemo() is called with several different cursors and  also
  636. for 43/50 line mode.
  637.  
  638.     nexttdemo() first sets the text cursor and prints the title string.
  639. It then runs a loop that process mouse events. A counter that shows the
  640. mouse position calls x() and y() which read variables that are  contin-
  641. uously  updated by the event handler via GetEvent().  Button status  is
  642. also  checked and displayed.  Released() is called to check for a  left
  643. button release event which will terminate the loop if the cursor is in-
  644. side the [Next] box at the time of release.  The loop will also be ter-
  645. minated  if the right button is double-clicked anywhere on the  screen.
  646. If the center button is double-clicked, the mouse is disabled until any
  647. keyboard key is pressed.  Pressing the <Shift> key and the left  button
  648. will  switch video pages (note that the alternate video page lacks  all
  649. the  functionality of the main page).  Pressing the <Ctrl> key  and the
  650. left button will set the global flag "done" which exits the rest of the
  651. text demo and proceeds with the graphics demo.
  652.  
  653.     graphicdemo()  works  the same way as textdemo().  In  addition  to
  654. trying several cursors, it also tests different mickey-to-pixel ratios.
  655. Notice that the ratio of 2 for the jet cursor will cause the cursor  to
  656. locate  on every fourth pixel as it moves across the  screen.  graphic-
  657. screen()  paints several background colors as well as black  and  white
  658. boxes in the center. These boxes demonstrate the use of the cursor bor-
  659. der created by the screen mask.  A graphical representation of a three-
  660. button mouse is again drawn to show the cursor position and button sta-
  661. tus.  nextgdemo()  sets the graphics cursor and  then  processes  mouse
  662. events,  checking the position and button status.  The last cursor is a
  663. ColorGraphicsCursor that is 9x39 pixels.
  664.  
  665.     During  the  graphics demo any multiclick events are  displayed  as
  666. different colors of the buttons on the screen (up to four).  The center
  667. button  is  set up as a repeater button, so that holding it  down  will
  668. generate multiple PRESSED events as well as multiclicks. A right button
  669. triple-click  will advance to the next cursor,  and <Ctrl>-left  button
  670. will exit the demo.
  671.  
  672. -----------------------------------------------------------------------
  673.  
  674. Supporting SuperVGA/VESA Modes
  675.  
  676.     As mentioned before,  the mouse driver performs the draw &  restore
  677. for the graphics cursor as it moves across the screen.  The drivers  do
  678. not  currently support color cursors or video modes beyond  640x480x16.
  679. The ColorGraphicsCursor feature of Mouse++ shows how color cursors  can
  680. be supported by manually drawing the cursor.  This method can be exten-
  681. ded to higher resolutions by modifying the VideoDraw() and CursorDraw()
  682. functions.
  683.  
  684.     If you are using a third party graphics library, the best method of
  685. supporting color or high-res modes is to simply use the functions  that
  686. are available in the library for manipulating bit images.  In the  BGI,
  687. these are getimage() and putimage().  The file cgc_bgi.cpp contains the
  688. code that uses the BGI to display the cursor.  This approach is  incom-
  689. plete in that it does not properly mask the cursor at the edges of  the
  690. screen (to display a partial cursor) nor does it attempt to insure that
  691. the viewport is set to the entire screen.  The ColorGraphicsCursor con-
  692. structor  in cgc_bgi.cpp converts the cgc image array to the BGI  image
  693. format,  after which getimage() and putimage() are used to display  the
  694. cursor.
  695.  
  696.     The BGI,  however, also does not support SuperVGA or VESA modes  as
  697. provided by Borland.  There is a set of VESA BGI drivers available that
  698. extend the BGI up to 1024x768x256. They are shareware and are available
  699. from the address listed below.  Using these drivers would allow cursors
  700. to be displayed in any mode,  but you would still have to take care  of
  701. masking the image at the screen edges and taking care of the viewport.
  702.  
  703. BGI VESA Drivers:
  704.  
  705.  Jordan Powell Hargrave          Internet: jh5y@andrew.cmu.edu
  706.  1000 Morewood Ave, Box #3277      Bitnet: jh5y%andrew.cmu.edu@cmccvb
  707.  Pittsburgh, PA 15213                UUCP: uunet!andrew.cmu.edu!jh5y
  708.  (412) 268-4488                Compuserve: [72510,1143]
  709.  
  710. -----------------------------------------------------------------------
  711.  
  712. The Mouse++ Functions
  713.  
  714. -----------------------------------------------------------------------
  715. Mouse::Exists()
  716.  
  717. Syntax:     unsigned char Exists(void)
  718.  
  719. Description:    Returns the value of an internal flag that is set by
  720.         the Mouse constructor.
  721.  
  722. Return Value:    1 if a mouse was found, 0 otherwise.
  723.  
  724. -----------------------------------------------------------------------
  725. Mouse::Visible()
  726.  
  727. Syntax:     unsigned char Visible(void)
  728.  
  729. Description:    Returns the status of the cursor visibility.
  730.  
  731. Return Value:    1 if the cursor is visible, 0 otherwise.
  732.  
  733. -----------------------------------------------------------------------
  734. Mouse::Buttons()
  735.  
  736. Syntax:     unsigned char Buttons(void)
  737.  
  738. Description:    Returns the number of buttons for the mouse
  739.  
  740. Return Value:    2 for a 2-button mouse, 3 for a 3-button mouse.
  741.  
  742. -----------------------------------------------------------------------
  743. Mouse::Button()
  744.  
  745. Syntax:     unsigned char Button(void)
  746.  
  747. Description:    Returns the status of the mouse buttons and shift keys
  748.         that is stored internal to the Mouse class. Call
  749.         Position() before using this function to insure an
  750.         accurate value, or when using the event handler call
  751.         GetEvent().
  752.  
  753. Return Value:    A mask corresponding to the status of the mouse buttons
  754.         and the shift keys (down=1, up=0):
  755.         -------------------------------------------------------
  756.         0x01    Left button
  757.         0x02    Right button
  758.         0x04    Center button
  759.         0x08    Either shift key
  760.         0x10    Right shift key
  761.         0x20    Left shift key
  762.         0x40    Alt key
  763.         0x80    Ctrl key
  764.  
  765. -----------------------------------------------------------------------
  766. Mouse::Enable()
  767.  
  768. Syntax:     void Enable(void)
  769.  
  770. Description:    Enables the mouse. This function must be called before
  771.         the mouse can be used for the first time, or after a
  772.         call to Disable(). A separate call to Show() is neces-
  773.         sary to display the cursor.
  774.  
  775. Return Value:    None.
  776.  
  777. -----------------------------------------------------------------------
  778. Mouse::Disable()
  779.  
  780. Syntax:     void Disable(void)
  781.  
  782. Description:    Disables the mouse and hides the cursor. If an event
  783.         handler has been installed, it is disabled and the
  784.         event buffer and multi-click buffer are cleared.
  785.  
  786. Return Value:    None.
  787.  
  788. -----------------------------------------------------------------------
  789. Mouse::Show()
  790.  
  791. Syntax:     void Show(void)
  792.  
  793. Description:    Turns on the mouse cursor.
  794.  
  795. Return Value:    None. Sets the internal visible flag to 1.
  796.  
  797. -----------------------------------------------------------------------
  798. Mouse::Hide()
  799.  
  800. Syntax:     void Hide(void)
  801.  
  802. Description:    Turns off the mouse cursor. All other mouse functions
  803.         will continue to operate. You should hide the cursor
  804.         prior to any screen writes to avoid having the mouse
  805.         restore an incorrect background.
  806.  
  807. Return Value:    None. Sets the internal visible flag to 0.
  808.  
  809. -----------------------------------------------------------------------
  810. Mouse::Position()
  811.  
  812. Syntax:     void Position(void)
  813.  
  814. Description:    Reads the cursor position and saves the coordinates
  815.         in internal variables. Use x() & y() to read the inter-
  816.                 nal variables. This function is not intended for use
  817.                 with the event handler.
  818.  
  819. Return Value:    None. Sets internal class position variables and button
  820.         status.
  821.  
  822. -----------------------------------------------------------------------
  823. Mouse::x()
  824.  
  825. Syntax:     int x(void)
  826.  
  827. Description:    Returns the x-position of the mouse cursor that is
  828.         stored internal to the Mouse class. Call Position()
  829.         before using this function to insure an accurate
  830.         value, or when using the event handler call GetEvent().
  831.  
  832. Return Value:    An integer that corresponds to the pixel location of
  833.         the cursor, even if the screen is in text mode.
  834.  
  835. -----------------------------------------------------------------------
  836. Mouse::y()
  837.  
  838. Syntax:     int y(void)
  839.  
  840. Description:    Returns the y-position of the mouse cursor that is
  841.         stored internal to the Mouse class. Call Position()
  842.         before using this function to insure an accurate
  843.         value, or when using the event handler call GetEvent().
  844.  
  845. Return Value:    An integer that corresponds to the pixel location of
  846.         the cursor, even if the screen is in text mode.
  847.  
  848. -----------------------------------------------------------------------
  849. Mouse::Motion()
  850.  
  851. Syntax:     void Motion(void)
  852.  
  853. Description:    Reads the internal motion counters which give the dis-
  854.         tance (in mickeys) the mouse has moved since the last
  855.         call to this function, and stores the values in class
  856.         variables. Use xCount() & yCount() to read these vari-
  857.         ables. This function is not intended for use with the
  858.         event handler.
  859.  
  860. Return Value:    None.
  861.  
  862. -----------------------------------------------------------------------
  863. Mouse::xCount()
  864.  
  865. Syntax:     int xCount(void)
  866.  
  867. Description:    Returns the distance the mouse has moved in the x-
  868.         direction. The distance is in mickeys, which may or may
  869.         not be the same as pixels, depending on the mickey-to-
  870.         pixel ratio. This function is useful for seeing if the
  871.         mouse has moved.
  872.  
  873. Return Value:    An integer that corresponds to the x distance in mic-
  874.         keys, regardless of screen mode.
  875.  
  876. -----------------------------------------------------------------------
  877. Mouse::yCount()
  878.  
  879. Syntax:     int yCount(void)
  880.  
  881. Description:    Returns the distance the mouse has moved in the y-
  882.         direction. The distance is in mickeys, which may or may
  883.         not be the same as pixels, depending on the mickey-to-
  884.         pixel ratio. This function is useful for seeing if the
  885.         mouse has moved.
  886.  
  887. Return Value:    An integer that corresponds to the y distance in mic-
  888.         keys, regardless of screen mode.
  889.  
  890. -----------------------------------------------------------------------
  891. Mouse::Move()
  892.  
  893. Syntax:     void Move(int x, int y)
  894.  
  895. Description:    Moves the cursor to a new position. x & y must be
  896.         pixel coordinates even if the screen is in text mode.
  897.  
  898. Return Value:    None.
  899.  
  900. -----------------------------------------------------------------------
  901. Mouse::Pressed()
  902.  
  903. Syntax:     int Pressed(int button)
  904.  
  905. Description:    In manual mode, this checks to see if button has been
  906.         pressed since the last call to this command. In event
  907.         driven mode, this checks to see if the current event
  908.         was triggered by button being pressed. button can be 0
  909.         (LEFTBUTTON), 1 (RIGHTBUTTON), or 2 (CENTERBUTTON).
  910.  
  911. Return Value:    1 if button has a pressed event, 0 otherwise.
  912.  
  913. -----------------------------------------------------------------------
  914. Mouse::Released()
  915.  
  916. Syntax:        int Released(int button)
  917.  
  918. Description:    In manual mode, this checks to see if button has been
  919.         released since the last call to this command. In event
  920.         driven mode, this checks to see if the current event
  921.         was triggered by button being released. button can be 0
  922.         (LEFTBUTTON), 1 (RIGHTBUTTON), or 2 (CENTERBUTTON).
  923.  
  924. Return Value:    1 if button has a released event, 0 otherwise.
  925.  
  926. -----------------------------------------------------------------------
  927. Mouse::LB_Dn()
  928.  
  929. Syntax:     unsigned char LB_Dn(void)
  930.  
  931. Description:    Returns the status of the left button.
  932.  
  933. Return Value:    1 if the left button is pressed, 0 otherwise.
  934.  
  935. -----------------------------------------------------------------------
  936. Mouse::RB_Dn()
  937.  
  938. Syntax:     unsigned char RB_Dn(void)
  939.  
  940. Description:    Returns the status of the right button.
  941.  
  942. Return Value:    1 if the right button is pressed, 0 otherwise.
  943.  
  944. -----------------------------------------------------------------------
  945. Mouse::CB_Dn()
  946.  
  947. Syntax:     unsigned char CB_Dn(void)
  948.  
  949. Description:    Returns the status of the center button.
  950.  
  951. Return Value:    1 if the center button is pressed, 0 otherwise.
  952.  
  953. -----------------------------------------------------------------------
  954. Mouse::xLimit()
  955.  
  956. Syntax:     void xLimit(int min, int max)
  957.  
  958. Description:    Sets the limit that the cursor can move in the x-
  959.         direction. min & max must be pixel values even if the
  960.         screen is in text mode.
  961.  
  962. Return Value:    None.
  963.  
  964. -----------------------------------------------------------------------
  965. Mouse::yLimit()
  966.  
  967. Syntax:     void yLimit(int min, int max)
  968.  
  969. Description:    Sets the limit that the cursor can move in the y-
  970.         direction. min & max must be pixel values even if the
  971.         screen is in text mode.
  972.  
  973. Return Value:    None.
  974.  
  975.  
  976. -----------------------------------------------------------------------
  977. Mouse::xyLimit()
  978.  
  979. Syntax:     void xyLimit(int xmin, int xmax, int ymin, int ymax)
  980.  
  981. Description:    Sets the limits that the cursor can move in the x- &
  982.         y-direction. Limits must be pixel values even if the
  983.         screen is in text mode.
  984.  
  985. Return Value:    None.
  986.  
  987.  
  988. -----------------------------------------------------------------------
  989. Mouse::GetVideoPage(void);
  990.  
  991. Syntax:     int GetVideoPage(void)
  992.  
  993. Description:    Gets the video page number for which the mouse cursor
  994.         is currently active. This may or may not be the same
  995.         as the video page that is currently being displayed on
  996.         the screen.
  997.  
  998. Return Value:    The number of the mouse cursor's current video page.
  999.  
  1000. -----------------------------------------------------------------------
  1001. Mouse::SetVideoPage(void);
  1002.  
  1003. Syntax:        void SetVideoPage(int page);
  1004.  
  1005. Description:    Sets the video page for which the mouse cursor will be
  1006.         active. Normally this will be the same as the displayed
  1007.         video page but it does not have to be.
  1008.  
  1009. Return Value:    None.
  1010.  
  1011. -----------------------------------------------------------------------
  1012. Mouse::SetCursor()
  1013.  
  1014. Syntax:     void SetCursor(TextCursor& cursor)
  1015.         void SetCursor(GraphicsCursor& cursor)
  1016.         void SetCursor(ColorGraphicsCursor& cursor)
  1017.  
  1018. Description:    Sets the text cursor as described by the TextCursor
  1019.         class or the graphics cursor as described by the
  1020.                 GraphicsCursor or ColorGraphicsCursor class.
  1021.  
  1022. Return Value:    None.
  1023.  
  1024. -----------------------------------------------------------------------
  1025. Mouse::MickToPix()
  1026.  
  1027. Syntax:     void MickToPix(int horiz, int vert)
  1028.  
  1029. Description:    Sets the mickey-to-pixel ratio. A mickey is a motion
  1030.         signal sent by the mouse and occurs every 1/200th inch
  1031.         for most mice. horiz passes the number of mickeys re-
  1032.         quired for an 8 pixel horizontal movement, and vert
  1033.         passes the number of mickeys required for an 8 pixel
  1034.         vertical movement. The constructor sets these to 8 and
  1035.         16, respectively.
  1036.  
  1037. Return Value:    None.
  1038.  
  1039. -----------------------------------------------------------------------
  1040. Mouse::SetSpeedThreshold()
  1041.  
  1042. Syntax:     void SetSpeedThreshold(unsigned speed)
  1043.  
  1044. Defaults:    speed = 64
  1045.  
  1046. Description:    Sets the threshold at which the cursor speed doubles.
  1047.         speed is in mickeys-per-second. Supposedly, this func-
  1048.         tion is only available for Logitech mice.
  1049.  
  1050. Return Value:    None.
  1051.  
  1052. -----------------------------------------------------------------------
  1053. Mouse::InBox()
  1054.  
  1055. Syntax:     int InBox(int left, int top, int right, int bottom)
  1056.  
  1057. Description:    Checks if the mouse cursor is located within a rec-
  1058.         tangle. Rectangle limits should be in pixels regardless
  1059.         of screen mode.
  1060.  
  1061. Return Value:    1 if the cursor is in the rectangle, 0 otherwise.
  1062.  
  1063. -----------------------------------------------------------------------
  1064. Mouse::Exclude()
  1065.  
  1066. Syntax:     void Exclude(int left, int top, int right, int bottom)
  1067.  
  1068. Description:    Sets up an exclusion area in which the mouse cursor
  1069.         automatically turns itself off. This is not the same as
  1070.         the exclude function that is built into the mouse, and
  1071.         must be continuously called in a loop. Rectangle limits
  1072.         should be in pixels regardless of screen mode.
  1073.  
  1074. Return Value:    None.
  1075.  
  1076. -----------------------------------------------------------------------
  1077. Mouse::SetClickThreshold()
  1078.  
  1079. Syntax:     void SetClickThreshold(unsigned time)
  1080.  
  1081. Defaults:    time = 250 (ms)
  1082.  
  1083. Description:    Sets the threshold at which sequential clicks are regi-
  1084.         stered as multi-clicks. time is in milliseconds.
  1085.  
  1086. Return Value:    None.
  1087.  
  1088. -----------------------------------------------------------------------
  1089. Mouse::MultiClick()
  1090.  
  1091. Syntax:     int MultiClick(int button)
  1092.  
  1093. Description:    Checks for multi-clicks of a button. button can be 0
  1094.         (LEFTBUTTON), 1 (RIGHTBUTTON), or 2 (CENTERBUTTON).
  1095.  
  1096. Return Value:    Current number of multi-clicks.
  1097.  
  1098. -----------------------------------------------------------------------
  1099. Mouse::DoubleClick()
  1100.  
  1101. Syntax:     int DoubleClick(int button)
  1102.  
  1103. Description:    Checks for double-clicks of a button. button can be 0
  1104.         (LEFTBUTTON), 1 (RIGHTBUTTON), or 2 (CENTERBUTTON).
  1105.  
  1106. Return Value:    1 if button has been double-clicked, 0 otherwise.
  1107.  
  1108. -----------------------------------------------------------------------
  1109. Mouse::ClearClick()
  1110.  
  1111. Syntax:     void ClearClick(int button)
  1112.  
  1113. Defaults:    button = 7 (all buttons)
  1114.  
  1115. Description:    Resets the multi-click status of button. button can be
  1116.         0 (LEFTBUTTON), 1 (RIGHTBUTTON), or 2 (CENTERBUTTON).
  1117.  
  1118. Return Value:    None.
  1119.  
  1120. -----------------------------------------------------------------------
  1121. Mouse::SetRepeatRate()
  1122.  
  1123. Syntax:     void SetRepeatRate(unsigned char button,
  1124.                                    unsigned delay, unsigned rate);
  1125.  
  1126. Defaults:    button = LEFTBUTTON
  1127.         delay  = 250 (ms)
  1128.                 rate   = 150 (ms)
  1129.  
  1130. Description:    Sets the threshold at which sequential clicks are regi-
  1131.         stered as multi-clicks. time is in milliseconds and de-
  1132.         faults to 250.
  1133.  
  1134. Return Value:    None.
  1135.  
  1136. -----------------------------------------------------------------------
  1137. Mouse::InstallHandler()
  1138.  
  1139. Syntax:     void InstallHandler(unsigned mask,
  1140.                     void interrupt (*fn)(void))
  1141. Alt. Syntax:    void InstallHandler(MouseEventHandler handler)
  1142.  
  1143. Defaults:    fn = MouseHandler()
  1144.  
  1145. Description:    Installs an interrupt handler function which is automa-
  1146.         tically run whenever an event occurs that is included
  1147.                 in the mask. The mouse driver loads the CPU registers
  1148.                 with mouse information before calling the function.
  1149.                 Therefore, the first action should be to save this in-
  1150.                 formation to an event buffer, which can be accomplished
  1151.                 by calling the Save() function. The remaining function
  1152.                 code should be kept to a minimum, and the function MUST
  1153.                 be terminated with the EventExit() macro. The mask bits
  1154.                 are described in Table X. If a function pointer is not
  1155.                 passed in the parameter list, then the default handler
  1156.                 MouseHandler() will be used.
  1157.  
  1158. Return Value:    None.
  1159.  
  1160. -----------------------------------------------------------------------
  1161. Mouse::Save()
  1162.  
  1163. Syntax:     void Save(int event, int button, int x, int y,
  1164.               int xcount, int ycount)
  1165.  
  1166. Description:    Stores the passed parameters in the event buffer. This
  1167.         should be the first function called from an event hand-
  1168.         ler routine. See the default handler MouseHandler() for
  1169.         details.
  1170.  
  1171. Return Value:    None.
  1172.  
  1173. -----------------------------------------------------------------------
  1174. Mouse::GetEvent()
  1175.  
  1176. Syntax:     void GetEvent(void)
  1177.  
  1178. Description:    Gets the next event from the event buffer and loads the
  1179.         parameters into class variables.
  1180.  
  1181. Return Value:    None.
  1182.  
  1183. -----------------------------------------------------------------------
  1184. Mouse::ClearEvent()
  1185.  
  1186. Syntax:     void ClearEvent(void)
  1187.  
  1188. Description:    Clears the current event from the internal class varia-
  1189.         bles.
  1190.  
  1191. Return Value:    None.
  1192.  
  1193. -----------------------------------------------------------------------
  1194. Mouse::ClearBuffer()
  1195.  
  1196. Syntax:     void ClearBuffer(void)
  1197.  
  1198. Description:    Clears the event buffer.
  1199.  
  1200. Return Value:    None.
  1201.  
  1202. -----------------------------------------------------------------------
  1203.  
  1204. References
  1205. 1.  Kent Porter, "Mouse Mysteries, Part I: Text", Turbo Technix, Vol. 
  1206.     1, No. 4, pp. 52-67, May/June 1988.
  1207. 2.  Kent Porter, "Mouse Mysteries, Part II: Graphics", Turbo Technix, 
  1208.     Vol. 1, No. 5, pp. 42-53, July/August 1988.
  1209. 3.  Terry Dettmann, DOS Programmers Reference, Part V: Reference, Mouse 
  1210.     Functions, pp. 717-739, Que, 1989.
  1211. 4.  Ralf Brown, Interrupt List, Release 31, July 12, 1992. This is 
  1212.     available in the Public Domain as INTER31A.ZIP, INTER31B.ZIP, and
  1213.     INTER31C.ZIP.
  1214.