// Demostraci¢n del uso del RATON en SVGA
// 					 	Jos‚ David Guill‚n
//
// ßßßßßßßßßßßßßßß
// ßFuTuReßViSiOnß
// ßßßßßßßßßßßßßßß
// ßßÜÜÜÜÜßÜÜÜßßßß
// ßß    ÛßÛ  ßÜßß
// ßßÜ   ÛßÛ   Ûßß
// ßßßÜÜÜßßÛÜÜß ßß
//
//
//

#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>

void InicializaSVGA(void);
void PreparaCuadricula256col(void);
extern int far _Cdecl Svga256_fdriver[];
int huge    DetectVGA256(){  return 2; }

#define T  255
#define C1 31
#define C2 4
#define C3 12


#define Ancho_Pantalla 640
#define Largo_Pantalla 640

unsigned char Puntero [ /* 21 * 28 */ ] = {
	  T,  T,  T,  T,  T,  T, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T, C1, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T, C1, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T,  T,  T, C1, C3, C2, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T,  T, C1, C3, C3, C2, C2, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T, C1, C3, C3, C2, C2, C2, C2, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T, C1, C1, C1, C1, C2, C2, C2, C1, C1, C1, C1,  T,  T,  T,  T,  T, C1, C1, C1, C1, C1, C1, C1, C1,  T,  T,  T
       ,  T,  T,  T,  T, C1, C3, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T, C1, C2, C2, C2, C2, C2, C2, C2, C2, C1,  T,  T
       ,  T,  T,  T,  T, C1, C3, C2, C2, C1,  T,  T,  T,  T,  T,  T, C1, C2, C2, C2, C1, C1, C1, C1, C2, C2, C2, C1,  T
       ,  T,  T,  T,  T, C1, C3, C2, C2, C1,  T,  T,  T,  T,  T, C1, C2, C2, C2, C1,  T,  T,  T,  T, C1, C2, C2, C2, C1
       ,  T,  T,  T,  T, C1, C3, C2, C2, C1,  T,  T,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T,  T,  T, C1, C2, C2, C1,  T
       ,  T,  T,  T, C1, C3, C2, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T, C1, C1,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T
       ,  T,  T, C1, C3, C2, C2, C1, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T,  T
       ,  T, C1, C3, C2, C2, C1,  T, C1, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T,  T,  T
       , C1, C3, C2, C2, C1,  T,  T,  T, C1, C2, C2, C2, C1,  T,  T,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T, C1, C1,  T,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T, C1, C1,  T,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T, C1, C2, C2, C1,  T,  T,  T,  T,  T
       ,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T,  T, C1, C1,  T,  T,  T,  T,  T,  T
			  };

char raton = 0;
unsigned char *Fondo_Raton;

int X_Mouse, Y_Mouse;

int Anclar_Raton(void);
void Inicializa_Raton(int x1, int y1, int x2, int y2);
unsigned char  Pon_Pixel( unsigned long y, unsigned long x, unsigned char color );

void main( void )
 {
  char Resultado;

   InicializaSVGA();

   PreparaCuadricula256col();

   Inicializa_Raton( 10, 10, 630, 470);

   if ( !raton )     return;

    Resultado = Anclar_Raton();

    // Regresamos al modo texto
    restorecrtmode();

   if ( Resultado )
    {
     if ( X_Mouse == Y_Mouse && Y_Mouse == -1 )
			     cprintf( " Se pulso una tecla, 1§Scan Code: % 3d \n\r", getch() );
     else
			     cprintf( " Se pulso un Boton en X: % 3d  -- Y: % 3d \n\r", X_Mouse, Y_Mouse );
    }
    else
	 cprintf( " Error Interno de asignacion de memoria \n\r" );

 }


// los par metros son las cotas para el raton
void Inicializa_Raton(int x1, int y1, int x2, int y2)
{

int px = 50, py = 50;

if ( Y_Mouse != -1 && X_Mouse != -1 )
 {
  px = X_Mouse;   py = Y_Mouse;
 }

	union   REGS ent, sal;
	long         dir;

	ent.x.ax =   0;
	int86(0x33, &ent, &sal);          /* averigua si hay rat¢n conectado */

	raton = sal.x.ax;                /* indica a la variable global el estado
					    del raton */

 if(raton!=0) {

	ent.x.ax =  15;
	ent.x.cx =  5;
	ent.x.dx =  11;
	int86(0x33, &ent, &sal);               /* fija la raz¢n mickey/pixel */

	ent.x.ax =   7;
	ent.x.cx =  x1;
	ent.x.dx =  x2;
	int86(0x33, &ent, &sal);  /* fija la posici¢n m x. y m¡n. horizontal */

	ent.x.ax =   8;
	ent.x.cx =  y1;
	ent.x.dx =  y2;
	int86(0x33, &ent, &sal);    /* fija la posici¢n m x. y m¡n. vertical */

	ent.x.ax =   4;
	ent.x.cx =  px;
	ent.x.dx =  py;
	int86(0x33, &ent, &sal);	       /* fija la posici¢n del rat¢n */

	ent.x.ax =   2;
	int86(0x33, &ent, &ent);

 }
}


// De esta funci¢n solo se regresa cuando se pulse una tecla o un Boton.
// Devuelve 1 si todo va bien, o 0 si hay un error interno de gesti¢n.
int Anclar_Raton(void)
 {
  char i,j;
  union REGS io;
  io.x.ax = 3;

  static int Old_X_Mouse = X_Mouse, Old_Y_Mouse = Y_Mouse;
  char ok = 0, Draw = 1;


  if ( ( Fondo_Raton = (char *)malloc( 28*21 ) ) == NULL )
							return 0;

 do{
  if( Draw )
  {

  for( i = 0; i < 21; i++)
   for( j = 0; j < 28; j++ )
    {
     Fondo_Raton[ i*28 + j ] = getpixel( (j + X_Mouse), (i + Y_Mouse) );
     if( Puntero[ i*28 + j ] != 255 )
	     putpixel( (j + X_Mouse), (i + Y_Mouse), Puntero[ i*28 + j ] );
    }

  }
  Draw = 0;

  // Esperamos a que se mueva el raton / pulse un boton o una tecla
  do{
   // Gestionamos las teclas
   if ( kbhit() )
    {
      X_Mouse = Y_Mouse = -1;
      ok = 1;
      break;
    // Si no hay teclas, los par metros del RATON habr n cambiado
    } else {
      int86(0x33, &io, &io);    // lee posici¢n y estados del bot¢n
      X_Mouse = io.x.cx;
      Y_Mouse = io.x.dx;
      // ¨ Se Puls¢ Un BOTON ?
      //     B.Izquierdo       B. Derecho
      if (  (io.x.bx & 1) != 0 ||  ( (io.x.bx >> 1) & 1 ) != 0  )
       {
	ok = 1;
	break;
       } else
	 /* ¨ Se movi¢ el Puntero ? */
	 if ( X_Mouse != Old_X_Mouse || Y_Mouse != Old_Y_Mouse )
	  {
	   // Restauramos el contenido de la pantalla
	   for( i = 0; i < 21; i++)
	    for( j = 0; j < 28; j++ )
	      putpixel( ( j + Old_X_Mouse),  (i + Old_Y_Mouse), Fondo_Raton[ i*28 + j ] );

	   Old_X_Mouse = X_Mouse;
	   Old_Y_Mouse = Y_Mouse;
	   Draw = 1;
	   break;
	  }
    }
  }while( 1 );

 }while(!ok);

  // Restauramos el contenido de la pantalla
  for( i = 0; i < 21; i++)
   for( j = 0; j < 28; j++ )
     putpixel( ( j + Old_X_Mouse),  (i + Old_Y_Mouse), Fondo_Raton[ i*28 + j ] );

  free( Fondo_Raton );
  return 1;

 }




void InicializaSVGA(void) {

  int Gd = DETECT, Gm;
  int Drv, errorcode;

  installuserdriver("Svga256",DetectVGA256);

  initgraph(&Gd,&Gm,"");

  errorcode = graphresult();

if (errorcode != grOk)
{
   cprintf("Graphics error: %s\n", grapherrormsg(errorcode));
   cprintf("Presione una tecla para finalizar:");
   getch();
   exit(1);
}

}

void PreparaCuadricula256col(void)
 {
  int x, y, color = 0;

  for( y = 0; y < 16; y++ )
   for( x = 0; x < 16; x++ )
    {
     setcolor(color);
     setfillstyle( SOLID_FILL, color );
     bar( 40*x, 30*y, 40+40*x+40, 30+30*y);
     color++;
    }

 }