/* Translated by Kevin Brooks from C routines written Ken Porter */
/* December 11, 1990 */

#include <dos.h>

#include "mouse.hpp"

extern
const int HARDWARE = 1;                                /* cursor types */
extern
const int SOFTWARE = 0;

/* Following are implementations of the Microsoft mouse functions  */

resetRec&
Mouse::Reset ()
/* Resets mouse to default state. Returns pointer to a structure   */
/* indicating whether or not mouse is installed and, if so, how    */
/* many buttons it has.                                            */
/* Always call this function during program initialization.        */
{

  inreg.x.ax = 0;                                    /* function 0 */
  callMDD();
  exists = outreg.x.ax;
  nButtons = outreg.x.bx;
  resetRec resetrec(exists, nButtons);
  return resetrec;
} 

void 
Mouse::Show()
/* Makes the mouse cursor visible. Don't call if cursor is already */
/* visible, and alternate with calls to mHide.                     */
{
  inreg.x.ax = 1;                                    /* function 1 */
  callMDD();
} 

void 
Mouse::Hide()
/* Makes mouse cursor invisible. Movement and button activity are  */
/* still tracked. Do not call if cursor is already hidden, and     */
/* alternate with calls to mShow                                   */
{
  inreg.x.ax = 2;                                    /* function 2 */
  callMDD();
}

locRec&
Mouse::Pos()
/* Gets mouse cursor position and button status, returns pointer   */
/* to structure containing this info                               */
{
  inreg.x.ax = 3;                                    /* function 3 */
  callMDD();
  buttonStatus = outreg.x.bx;                   /* button status */
  column = outreg.x.cx;                        /* horiz position */
  row = outreg.x.dx;                            /* vert position */
  locRec locrec(buttonStatus, 1, column, row);
  return locrec;
}

void  
Mouse::Moveto(int newCol, int newRow)
/* Move mouse cursor to new position */
{
  inreg.x.ax = 4;                                    /* function 4 */
  inreg.x.cx = newCol;
  inreg.x.dx = newRow;
  callMDD();
}

locRec&
Mouse::Pressed(Button button)
/* Gets pressed info about named button: current status (up/down), */
/* times pressed since last call, position at most recent press.   */
/* Resets count and position info. Button 0 is left, 1 is right on */
/* Microsoft mouse.                                                */
/* Returns pointer to locRec structure containing info.            */
{

  inreg.x.ax = 5;                                    /* function 5 */
  inreg.x.bx = button;              /* request for specific button */
  callMDD();
  buttonStatus = outreg.x.ax;
  opCount = outreg.x.bx;
  column  = outreg.x.cx;
  row     = outreg.x.dx;
  locRec locrec(buttonStatus, opCount, column, row);
  return locrec;
}

locRec&
Mouse::Released(Button button)
/* Same as mPressed, except gets released info about button */
{

  inreg.x.ax = 6;                                    /* function 6 */
  inreg.x.bx = button;              /* request for specific button */
  callMDD();
  buttonStatus = outreg.x.ax;
  opCount = outreg.x.bx;
  column  = outreg.x.cx;
  row     = outreg.x.dx;

  // the 1 as the 2nd argument is a dummy
  locRec locrec(buttonStatus, 1, column, row);
  return locrec;
}

void  
Mouse::SetColRange(int hmin, int hmax)
/* Sets min and max horizontal range for mouse cursor. Moves   */
/* cursor inside range if outside when called. Swaps values if */
/* hmin and hmax are reversed.                                 */
{
  inreg.x.ax = 7;                                /* function 7 */
  inreg.x.cx = hmin;
  inreg.x.dx = hmax;
  callMDD();
}

void
Mouse::SetRowRange(int vmin, int vmax)
/* Same as mHminmax, except sets vertical boundaries. */
{
  inreg.x.ax = 8;                                    /* function 8 */
  inreg.x.cx = vmin;
  inreg.x.dx = vmax;
  callMDD();
}

void  
Mouse::GraphCursor (int hHot, int vHot, unsigned maskSeg,
                    unsigned maskOfs)
/* Sets graphic cursor shape */
{
  struct SREGS  seg;

  inreg.x.ax = 9;                                    /* function 9 */
  inreg.x.bx = hHot;                /* cursor hot spot: horizontal */
  inreg.x.cx = vHot;                  /* cursor hot spot: vertical */
  inreg.x.dx = maskOfs;
  seg.es = maskSeg;
  int86x (0x33, &inreg, &outreg, &seg);
} 

void  
Mouse::TextCursor (int curstype, unsigned arg1, unsigned arg2)
/* Sets text cursor type, where 0 = software and 1 = hardware)     */
/* For software cursor, arg1 and arg2 are the screen and cursor    */
/*   masks.                                                        */
/* For hardware cursor, arg1 and arg2 specify scan line start/stop */
/*   i.e. cursor shape.                                            */
{
  inreg.x.ax = 10;                                  /* function 10 */
  inreg.x.bx = curstype;
  inreg.x.cx = arg1;
  inreg.x.dx = arg2;
  callMDD();
} 

moveRec&
Mouse::Motion()
/* Reports net motion of cursor since last call to this function   */
{

  inreg.x.ax = 11;                                  /* function 11 */
  callMDD();

  // moverec.hCount = _CX;                                /* net horizontal */
  // moverec.vCount = _DX;                                  /* net vertical */

  hCount = outreg.x.cx;                                /* net horizontal */
  vCount = outreg.x.dx;                                  /* net vertical */

  moveRec moverec(hCount, vCount);
  return moverec;
}

void 
Mouse::InstTask (unsigned mask, unsigned taskSeg, unsigned taskOfs)
/* Installs a user-defined task to be executed upon one or more    */
/*   mouse events specified by mask.                               */
{
  struct SREGS  seg;

  inreg.x.ax = 12;                                  /* function 12 */
  inreg.x.cx = mask;
  inreg.x.dx = taskOfs;
  seg.es = taskSeg;
  int86x (0x33, &inreg, &outreg, &seg);
} 

void 
Mouse::LpenOn()
/* Turns on light pen emulation. This is the default condition.    */
{
  inreg.x.ax = 13;                                  /* function 13 */
  callMDD();
}

void 
Mouse::LpenOff()
/* Turns off light pen emulation. */
{
  inreg.x.ax = 14;                                  /* function 14 */
  callMDD();
}

void 
Mouse::Ratio(int horiz, int vert)
/* Sets mickey-to-pixel ratio, where ratio is R/8. Default is 16   */
/*   for vertical, 8 for horizontal */
{
  inreg.x.ax = 15;                                  /* function 15 */
  inreg.x.cx = horiz;
  inreg.x.dx = vert;
  callMDD();
}


